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 }