二叉查找树:
struct binary_search_node//二叉查找树结点结构 { int key; binary_search_node *left; binary_search_node *right; binary_search_node *p; binary_search_node(int k=0,binary_search_node *l=NULL, binary_search_node *r=NULL,binary_search_node* pa=NULL) { key=k; left=l; right=r; p=pa; } }; void inorder_tree_walk(binary_search_node *x) //中序遍历,按顺序输出关键字,时间复杂度O(n) { if(x!=NULL) { inorder_tree_walk(x->left); cout<<x->key<<" ";//如果这里用空格,再主程序中记得用endl清空缓存,否则无法显示 inorder_tree_walk(x->right); } } void inorder_tree_walk_no_recurse(binary_search_node *x) //非递归中序遍历,使用栈 { stack<binary_search_node *> s;//存储结点指针! 不是key while(x!=NULL||!s.empty()) { while(x!=NULL) { s.push(x); x=x->left; }//此时x为NULL if(!s.empty()) { x=s.top(); cout<<x->key<<" "; s.pop(); x=x->right; } } } void inorder_tree_walk_no_recurse_no_stack(binary_search_node *x) //非递归中序遍历,不使用栈 { binary_search_node *pre; while(x!=NULL) { if(x->left==NULL)//如果左儿子为空,直接输出,并向右遍历 { cout<<x->key<<" "; x=x->right; } else//如果左儿子不为空,找其前驱结点,即左子树的最右结点 { pre=x->left; while(pre->right!=NULL&&pre->right!=x) pre=pre->right; if(pre->right==NULL) //如果前驱的右儿子为空,表明还没访问过左子树,将前驱的右儿子设为自己,并向左遍历 { pre->right=x; x=x->left; } else //如果前驱的右儿子为自己,表明左子树已经访问过了,则将前驱的右儿子置空,输出结点,并向右遍历 { pre->right=NULL; cout<<x->key<<" "; x=x->right; } } } } binary_search_node* tree_search(binary_search_node *x,int k) //在x为根的树中查找关键字k,返回包含k的结点的指针,没有则返回NULL,O(h) { if(x==NULL || k==x->key) return x; if(k<x->key) return tree_search(x->left,k); else return tree_search(x->right,k); } binary_search_node* iteractive_tree_search(binary_search_node *x,int k) //查找关键字k的非递归版本 { while(x!=NULL && k!=x->key) { if(k<x->key) x=x->left; else x=x->right; } return x; } binary_search_node* tree_minimum(binary_search_node *x) //寻找最小结点 O(h) { while(x->left!=NULL) x=x->left; return x; } binary_search_node* tree_maximum(binary_search_node *x) //寻找最大结点 { while(x->right!=NULL) x=x->right; return x; } binary_search_node* tree_successor(binary_search_node *x) //寻找后继结点,没有则返回NULL,O(h) { if(x->right!=NULL)//如果x的右子树非空,后继即右子树的最左结点 return tree_minimum(x->right); binary_search_node* y=x->p; //如果x的右子树为空,向上查找,直到遇到某个是其父结点的左儿子的结点为止 while(y!=NULL && x==y->right) { x=y; y=y->p; } return y; } binary_search_node* tree_predecessor(binary_search_node *x) //寻找前驱结点 { if(x->left!=NULL) return tree_maximum(x->left); binary_search_node* y=x->p; while(y!=NULL && x==y->left) { x=y; y=y->p; } return y; } binary_search_node* tree_insert(binary_search_node *x,binary_search_node *z) //将结点z插入树中,返回插入后的根结点,O(h) { binary_search_node *y=NULL; binary_search_node *root=x; while(x!=NULL) { y=x;//y始终指向x的父结点 if(z->key<x->key) x=x->left; else x=x->right; } z->p=y; if(y==NULL)//树为空的情况 root=z; else if(z->key<y->key) y->left=z; else y->right=z; return root; } binary_search_node* tree_delete(binary_search_node *x,binary_search_node *z) //从根为x的树中删除结点z,O(h)分三种情况 //(1)z没有子女 (2)z只有一个子女 (3)z有两个子女 { binary_search_node *q,*y,*root; root=x; if(z->left==NULL || z->right==NULL)//1和2 y=z; else//3 y=tree_successor(z); if(y->left!=NULL) q=y->left; else q=y->right; if(q!=NULL)//2,3 q->p=y->p; if(y->p==NULL)//1,2,3删除的是根结点的情况 root=q; else if(y==y->p->left)//1,2,3 y->p->left=q; else//1,2,3 y->p->right=q; if(y!=z)//3,用z后继的内容替换z的内容 z->key=y->key; return root; }
已知树的前序和中序,求后序:
#include<stdio.h> #include<string.h> //二叉树结点的描述 typedef struct BinaryTreeNode { char data; struct BinaryTreeNode *lchild, *rchild; //左右孩子 }BinaryTreeNode,*BinaryTree; inline BinaryTreeNode* ConstructCore(char *startPreorder, char *endPreorder, char *startInorder, char *endInorder) { //前序遍历序列的第一个字符是根节点的值 char rootValue = startPreorder[0]; BinaryTreeNode* root = new BinaryTreeNode(); root->data = rootValue; root->lchild = root->rchild = NULL; if(startPreorder == endPreorder) { if(startInorder == endInorder && *startPreorder== *startInorder) return root; } //在中序遍历中找到根节点的值 char *rootInorder = startInorder; while(rootInorder <= endInorder && *rootInorder != rootValue) rootInorder++; int leftLength = rootInorder - startInorder; char *leftPreorderEnd = startPreorder + leftLength; if(leftLength > 0) { //构建左子树 root->lchild = ConstructCore(startPreorder+1, leftPreorderEnd, startInorder, rootInorder-1); } if(leftLength < endPreorder - startPreorder) { //构建右子树 root->rchild = ConstructCore(leftPreorderEnd+1, endPreorder, rootInorder+1, endInorder); } return root; } //分别在前序遍历和中序遍历的序列中确定左、右子树的子序列 inline BinaryTreeNode* Construct(char *preorder, char *inorder, int length) { if(preorder == NULL || inorder == NULL || length<=0) return NULL; return ConstructCore(preorder, preorder+length-1, inorder, inorder+length-1); } //后序遍历 inline void PostOrder(BinaryTreeNode *root) { if(root==NULL) return ; PostOrder(root->lchild); //递归调用,前序遍历左子树 PostOrder(root->rchild); //递归调用,前序遍历右子树 printf("%c", root->data); //输出数据 } //释放二叉树 inline void DeleteBinaryTree(BinaryTree root) { if(root) { DeleteBinaryTree(root->lchild); //释放左子树 DeleteBinaryTree(root->rchild); //释放右子树 delete root; //释放根结点 } } int main(void) { int length; char preorder[27],inorder[27]; while(scanf("%s",preorder)!=EOF) { scanf("%s",inorder); length = strlen(preorder); BinaryTreeNode* root = Construct(preorder, inorder, length); PostOrder(root); printf("\n"); DeleteBinaryTree(root); } return 0; }