1 #include<cstdio> 2 #include<stack> 3 4 typedef struct TNode *Position; 5 typedef Position BinTree; 6 7 struct TNode 8 { 9 int Data; 10 BinTree Left; 11 BinTree Right; 12 }; 13 14 /*二叉樹遞歸先序遍歷*/ 15 void PreorderTravseral(BinTree t) 16 { 17 if(t){ 18 printf("%d ",t->Data); 19 PreorderTravseral(t->Left); 20 PreorderTravseral(t->Right); 21 } 22 } 23 24 /*二叉樹遞歸中序遍歷*/ 25 void InorderTravseral(BinTree t) 26 { 27 if(t){ 28 InorderTravseral(t->Left); 29 printf("%d ",t->Data); 30 InorderTravseral(t->Right); 31 } 32 } 33 34 /*二叉樹遞歸後序遍歷*/ 35 void PostorderTravseral(BinTree t) 36 { 37 if(t){ 38 InorderTravseral(t->Left); 39 InorderTravseral(t->Right); 40 printf("%d ",t->Data); 41 } 42 } 43 44 /*二叉樹的非遞歸遍歷都須要使用數據結構棧棧*/ 45 /*二叉樹非遞歸先序遍歷*/ 46 void PreorderTraversal_unrecursive(BinTree t) 47 { 48 using std::stack; 49 stack<BinTree>s; 50 while(t || !s.empty()){ 51 while(t){ 52 s.push(t); 53 printf("%d ",t->Left); 54 t = t->Left; 55 } 56 if(!s.empty()){ 57 t = s.top(); 58 s.pop(); 59 t = t->Right; 60 } 61 } 62 } 63 64 /*二叉樹非遞歸中序遍歷*/ 65 void InorderTraversal_unrecursive(BinTree t) 66 { 67 using std::stack; 68 stack<BinTree>s; 69 while(t || !s.empty()){ 70 while(t){ 71 s.push(t); 72 t = t->Left; 73 } 74 if(!s.empty()){ 75 t = s.top(); 76 s.pop(); 77 printf("%d ",t->Data); 78 t = t->Right; 79 } 80 } 81 }
下面單獨介紹樹的後序遍歷非遞歸算法。
在樹的非遞歸後序遍歷,對於每一個根節點,要確保其左結點和右結點都被訪問了之後才能訪問根結點。沒有孩子則能夠直接訪問。若非上述兩種狀況,則將P的右孩子和左孩子依次入棧,這樣就保證了 每次取棧頂元素的時候,左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。node
1 void PostorderTraversal_unrecusive(BinTree t) 2 { 3 if(!t) 4 return; 5 stack<BinTree>s; 6 s.push(t); 7 BinTree cur,prev = NULL; 8 //對於兄弟結點,棧必定先彈出左兄弟,而後再彈出右兄弟 9 //棧元素排列順序必定是:根 右結點 左結點 10 while(!s.empty()){ 11 cur = s.top(); 12 if((cur->Left == NULL && cur->Data == NULL) || 13 prev != NULL && (prev == cur->Left || prev == cur->Right)){ 14 printf("%d ",cur->Data); 15 s.pop(); 16 prev = cur; 17 } 18 else{ 19 if(t->Right) 20 s.push(t->Right); 21 if(t->Left) 22 s.push(t->Left); 23 } 24 } 25 }
BST經常使用函數實現算法
1 typedef int ElementType; 2 typedef struct TNode *Position; 3 typedef Position BinTree; 4 struct TNode{ 5 ElementType Data; 6 BinTree Left; 7 BinTree Right; 8 }; 9 10 BinTree Insert( BinTree BST, ElementType X ) 11 { 12 if(!BST){ 13 BinTree node = (BinTree)malloc(sizeof(struct TNode)); 14 node->Left = node->Right = NULL; 15 node->Data = X; 16 return node; 17 } 18 else if(X > BST->Data) 19 BST->Right = Insert(BST->Right,X); 20 else if(X < BST->Data) 21 BST->Left = Insert(BST->Left,X); 22 23 return BST; 24 } 25 26 BinTree Delete( BinTree BST, ElementType X ) 27 { 28 Position temp; 29 if(!BST){ 30 printf("Not Found\n"); 31 return BST; 32 } 33 else if(X > BST->Data) 34 BST->Right = Delete(BST->Right,X); 35 else if(X < BST->Data) 36 BST->Left = Delete(BST->Left,X); 37 else if(X == BST->Data){ 38 if(BST->Right && BST->Left){ 39 temp = FindMin(BST->Right); 40 BST->Data = temp->Data; 41 BST->Right = Delete(BST->Right, BST->Data); 42 } 43 else{ 44 temp = BST; 45 if(!BST->Left) 46 BST = BST->Right; 47 else 48 BST = BST->Left; 49 50 free(temp); 51 } 52 } 53 return BST; 54 } 55 56 57 Position Find( BinTree BST, ElementType X ) 58 { 59 if(!BST) 60 return NULL; 61 else if(X > BST->Data) 62 return Find(BST->Right,X); 63 else if(X < BST->Data) 64 return Find(BST->Left,X); 65 else 66 return BST; 67 } 68 69 Position FindMin( BinTree BST ) 70 { 71 if(!BST) 72 return NULL; 73 while(BST->Left) 74 BST = BST->Left; 75 return BST; 76 } 77 78 Position FindMax( BinTree BST ) 79 { 80 if(!BST) 81 return NULL; 82 while(BST->Right) 83 BST = BST->Right; 84 return BST; 85 }
由於BST不是嚴格O(logn)的。極端狀況它有可能就退化成了一個鏈表。爲了提升效率,因而就有了自平衡二叉樹(AVL)。咱們再插入結點後經過旋轉來保證二叉樹的平衡(所謂平衡,其實就是讓結點在左右子樹分佈的更均勻,對於每個子樹的結點,左右子樹高度的絕對值的差不超過1)。數據結構
對於A結點來講,它的平衡被破壞了,咱們就用圖中的旋轉來使其再次平衡。要注意的是,右單旋的這個名字頗有誤導性的,至少我一開始記錯了!右單旋並非向右旋轉,而是新插入的結點在根結點的右子樹的根結點的右子樹上(因此又叫RR旋轉)。函數
左單旋同理。spa
左單旋就是LL旋轉。code
到了左右旋的狀況下,新結點的插入再也不是像以往同樣一路下去不改變方向了。左右旋對應的狀況是新結點插入了根結點的左子樹的根節點的右子樹上。旋轉時咱們須要從後往前旋轉,即先旋轉B(根節點的左子樹的根結點),對於B來講,結點插入在它的右子樹上,因此先對B結點進行右單旋。最後對於A進行旋轉。對於A來講,新結點插入在它的左子樹上,再對A進行左旋。左右旋其實就是兩種單旋的組合。右左旋同理。blog
下圖爲右左旋。遞歸
Codeit
1 #include<algorithm> 2 #include<cstdlib> 3 using namespace std; 4 struct AVLnode{ 5 int val; 6 AVLnode* left; 7 AVLnode* right; 8 }; 9 typedef AVLnode* AVL; 10 typedef AVL Poisition; 11 AVL NewNode(int val) 12 { 13 AVL temp = (AVL)malloc(sizeof(AVLnode)); 14 temp->val = val; 15 temp->left = temp->right = NULL; 16 return temp; 17 } 18 19 AVL SingleLeftRotation(AVL tree) 20 { 21 AVL temp = tree->left; 22 tree->left = temp->right; 23 temp->right = tree; 24 return temp; 25 } 26 27 AVL SingleRightRotation(AVL tree) 28 { 29 AVL temp = tree->right; 30 tree->right = temp->left; 31 temp->left = tree; 32 return temp; 33 } 34 35 36 AVL LeftRightRotation(AVL tree) 37 { 38 tree->left = SingleRightRotation(tree->left); 39 return SingleLeftRotation(tree); 40 } 41 42 AVL RightLeftRotation(AVL tree) 43 { 44 tree->right = SingleLeftRotation(tree->right); 45 return SingleRightRotation(tree); 46 } 47 48 49 int GetHeight(AVL tree)//給一個根結點,計算樹的高度 50 { 51 if(!tree) 52 return 0; 53 else 54 return max(GetHeight(tree->left),GetHeight(tree->right))+1; 55 } 56 57 Poisition InsertNode(AVL tree,int v) 58 { 59 if(!tree){ 60 tree = NewNode(v); 61 } 62 else{ 63 if(v > tree->val){ 64 tree->right = InsertNode(tree->right,v);//插入的地方在右邊 65 if(GetHeight(tree->right) - GetHeight(tree->left) == 2){//失衡了 66 if(v > tree->right->val)//插入到右子樹的右邊,右單旋 67 tree = SingleRightRotation(tree); 68 else if(v < tree->right->val)//插入到右子樹的左邊,右左旋 69 tree = RightLeftRotation(tree); 70 } 71 } 72 else if(v < tree->val){ 73 tree->left = InsertNode(tree->left,v);//插入到左子樹上 74 if(GetHeight(tree->left) - GetHeight(tree->right) == 2){//失衡了 75 //不建議對子樹的高度進行儲存,現用現算,不然不易更新 76 if(v > tree->left->val)//左子樹的右子樹上,左右旋 77 tree = LeftRightRotation(tree); 78 else if(v < tree->left->val)//左子樹的左子樹上,左單旋 79 tree = SingleLeftRotation(tree); 80 } 81 } 82 } 83 return tree; 84 }