5.2 二叉樹 算法
咱們寫一個二叉樹,它支持樹的插入,刪除,查詢和遍歷,並且左子樹的數據都小於右子樹的數據(PS:樹實際上很難的,想深刻了解的話,能夠去看看<算法導論>,什麼紅黑樹啊,B樹啊什麼的,反正我沒看懂就是了--估計是我太菜了^_^): 數據結構
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct TREE{ int data; struct TREE *leftChild; struct TREE *rightChild; }Tree; void insertTree( Tree *tree, int data ); void deleteTree( Tree *tree, int data ); int searchTree( Tree *tree, int data ); void showTree( Tree *tree ); int main( void ) { Tree *tree = ( Tree * )malloc( sizeof( Tree ) ); tree->leftChild = tree->rightChild = NULL; insertTree( tree, 5 ); insertTree( tree, 3 ); insertTree( tree, 2 ); insertTree( tree, 4 ); insertTree( tree, 8 ); insertTree( tree, 7 ); insertTree( tree, 9 ); insertTree( tree, 6 ); showTree( tree->leftChild ); deleteTree( tree, 3 ); deleteTree( tree, 5 ); deleteTree( tree, 6 ); printf("\n"); showTree( tree->leftChild ); printf("\n"); if ( searchTree( tree, 8 ) ){ printf("8 in the tree\n"); } else{ printf("8 not in the tree\n"); } if ( searchTree( tree, 13 ) ){ printf("13 in the tree\n"); } else{ printf("13 not in the tree\n"); } return 0; } void insertTree( Tree *tree, int data ) { Tree *newTree = ( Tree * )malloc( sizeof( Tree ) ); newTree->leftChild = newTree->rightChild = NULL; newTree->data = data; if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){ tree->leftChild = newTree; } else{ tree = tree->leftChild; while ( NULL != tree ){ if ( data == tree->data ){ return; } else if ( data < tree->data ){ if ( NULL == tree->leftChild ){ tree->leftChild = newTree; return; } tree = tree->leftChild; } else{ if ( NULL == tree->rightChild ){ tree->rightChild = newTree; return; } tree = tree->rightChild; } } } } /* 找到被刪除節點的右子樹的最小節點,刪除最小節點而且將其值賦給被刪除的節點 */ void deleteTree( Tree *tree, int data ) { Tree *prevTree = ( Tree * )malloc( sizeof( Tree ) ); //指向刪除節點的前一個節點 Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) ); //處理被刪除的節點擁有左右樹的特殊狀況 prevTree = tree; tree = tree->leftChild; while ( tree ){ if ( data < tree->data ){ prevTree = tree; tree = tree->leftChild; } else if ( data > tree->data ){ prevTree = tree; tree = tree->rightChild; } else{ //刪除節點的左子樹爲空,則直接用右子樹替換該節點 if ( NULL == tree->leftChild ){ if ( data == prevTree->leftChild->data ){ prevTree->leftChild = prevTree->leftChild->rightChild; } else{ prevTree->rightChild = prevTree->rightChild->rightChild; } } else if ( NULL == tree->rightChild ){ //刪除節點的右子樹爲空,則直接用左子樹替換該節點 if ( data == prevTree->leftChild->data ){ prevTree->leftChild = prevTree->leftChild->leftChild; } else{ prevTree->rightChild = prevTree->rightChild->leftChild; } } else{ tempTree = tree; //保存右子樹中最小節點的前節點 tree = tree->rightChild; while ( tree->leftChild ){ //找到最小節點 tempTree = tree; tree = tree->leftChild; } //替換數據 if ( data == prevTree->leftChild->data ){ prevTree->leftChild->data = tree->data; } else{ prevTree->rightChild->data = tree->data; } //刪除最小節點 if ( tempTree->leftChild->data == tree->data ){ tempTree->leftChild = tree->rightChild; } else{ tempTree->rightChild = tree->rightChild; } } break; } } } int searchTree( Tree *tree, int data ) { tree = tree->leftChild; while ( tree ){ if ( data == tree->data ){ return 1; } else if ( data < tree->data ){ tree = tree->leftChild; } else{ tree = tree->rightChild; } } return 0; } void showTree( Tree *tree ) { if ( tree ){ printf("%d ", tree->data ); showTree( tree->leftChild ); showTree( tree->rightChild ); } }
發現效率有點低@_@ 學習
二叉樹有四種遍歷方式:前序遍歷,中序遍歷,後序遍歷,層序遍歷.其中,層序遍歷比較難.因此嘗試寫下代碼看看: .net
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 100 typedef struct TREE{ int data; struct TREE *leftChild; struct TREE *rightChild; }Tree; Tree *stack[ MAX_SIZE ]; int top = 0; int rear = 0; void insertTree( Tree *tree, int data ); void showTree( Tree *tree ); int main( void ) { Tree *tree = ( Tree * )malloc( sizeof( Tree ) ); tree->leftChild = tree->rightChild = NULL; insertTree( tree, 5 ); insertTree( tree, 3 ); insertTree( tree, 2 ); insertTree( tree, 4 ); insertTree( tree, 8 ); insertTree( tree, 7 ); insertTree( tree, 9 ); insertTree( tree, 6 ); showTree( tree->leftChild ); return 0; } void insertTree( Tree *tree, int data ) { Tree *newTree = ( Tree * )malloc( sizeof( Tree ) ); newTree->leftChild = newTree->rightChild = NULL; newTree->data = data; if ( ( NULL == tree->leftChild ) && ( NULL == tree->rightChild ) ){ tree->leftChild = newTree; } else{ tree = tree->leftChild; while ( NULL != tree ){ if ( data == tree->data ){ return; } else if ( data < tree->data ){ if ( NULL == tree->leftChild ){ tree->leftChild = newTree; return; } tree = tree->leftChild; } else{ if ( NULL == tree->rightChild ){ tree->rightChild = newTree; return; } tree = tree->rightChild; } } } } void showTree( Tree *tree ) { stack[ rear++ ] = tree; while ( 1 ){ tree = stack[ top++ ]; if ( tree ){ printf("%d ", tree->data ); if ( tree->leftChild ){ stack[ rear++ ] = tree->leftChild; } if ( tree->rightChild ){ stack[ rear++ ] = tree->rightChild; } } else{ break; } } }
5.4 二叉樹的其餘操做 指針
1. 二叉樹的複製 code
直接將頭指針賦值便可. blog
2. 判斷二叉樹的等價性 排序
須要用到遞歸,代碼相似以下: 遞歸
int equal(tree_pointer first, tree_pointer second ) { return ((!first && !second)||(first && second && (first->data == second->data)) && equal(first->left_child, second->left_child) && equal(first->right_child, second->right_child)) }
void swapLeftRight( Tree *tree ) { if ( tree ){ Tree *tempTree = ( Tree * )malloc( sizeof( Tree ) ); tempTree = tree->leftChild; tree->leftChild = tree->rightChild; tree->rightChild = tempTree; swapLeftRight( tree->leftChild ); swapLeftRight( tree->rightChild ); } }
5.5 線索二叉樹 隊列
線索二叉樹經過增長數據結構而簡化遍歷,這種想法是否可取得進一步討論.
5.6 堆
1. 最大樹是指在樹中,一個結點有兒子結點,其關鍵字都不小於兒子結點的關鍵字值.最大堆是一棵徹底二叉樹,也是一棵最大樹.
2. 最小數是指在樹中,一個結點有兒子結點,其關鍵字都不大於兒子結點的關鍵字值.最小堆是一棵徹底二叉樹,也是一棵最小數.
http://my.oschina.net/voler/blog/167320
以前學習算法導論的時候,堆排序作了很詳細的筆記.因此這裏就再也不重複了(不過有點忘記了.仍是得找段時間好好研究一下算法導論).
5.7 二叉搜索樹
這篇文章剛開始的時候就用一個程序開頭,就是二叉搜索樹的增刪查.故再也不重複.