树的基本知识点(未完)

来源:互联网 发布:手机通话变声软件 编辑:程序博客网 时间:2024/06/05 20:37

1、基本概念

(1)递归定义

(2)术语

...这些从略了


2、表示

比较流行的表示法叫做Firstchild-Nextsibling:

struct Tree{DataType Data;TreePtr FirstChild;TreePtr NextSibling;};



3、二叉树

(1)基本性质(其实很多是树的性质)

①除了叶子之外的所有点叫做“内点”,也就是入度为1,出度不为0的点,或者说,也就是有孩子的顶点。假如一棵满m叉树的内点是i,则它一共有mi+1个顶点

②高度为h的m叉树最多有m^h个叶子

注:单个节点的树高在一些书上是1,一些是0,个人觉得。。

③For any nonempty binary tree, n0 = n2 + 1 where n0 is the number of leaf nodes and n2 the number of nodes of degree 2.


(2)重要的问题

①前序遍历(递归和非递归)

②中序遍历(递归和非递归)

③后序遍历(递归和非递归)

④层次遍历

关于上面4个问题可以参看这个测试程序:

#include<iostream>#include<stack>#include<queue>using namespace std;typedef char DataType;typedef struct BiTreeNode* TreePtr;struct BiTreeNode{DataType dt;TreePtr left;TreePtr right;};/*递归建立二叉树用‘#’表示节点为空例如:a/\bc/\/\d#e#/\/\# ## #输入前序:abd###ce###即可建立起对应的二叉树*/TreePtr create_tree(){TreePtr t;char c;cin>>c;if(c=='#')t=NULL;else{//建立顺序是前序t=new BiTreeNode;t->dt=c;t->left=create_tree();t->right=create_tree();}return t;}/*前序遍历的递归写法:根、左、右*/void preorder(TreePtr t){if(t==NULL)return;cout<<t->dt;preorder(t->left);preorder(t->right);}/*前序遍历非递归*/void preorder2(TreePtr t){stack<TreePtr> s;if(!t){cout<<"empty tree"<<endl;return;}while(t||!s.empty()){while(t){cout<<t->dt;s.push(t);t=t->left;}if(!s.empty()){t=s.top();s.pop();t=t->right;}}}/*中序遍历的递归写法:左、根、右*/void inorder(TreePtr t){if(t==NULL)return;inorder(t->left);cout<<t->dt;inorder(t->right);}/*中序遍历非递归*/void inorder2(TreePtr t){stack<TreePtr> s;if(!t){cout<<"empty tree"<<endl;return;}while(t||!s.empty()){while(t){s.push(t);t=t->left;}t=s.top();s.pop();cout<<t->dt;t=t->right;}}/*后序遍历的递归写法:左、右、根*/void postorder(TreePtr t){if(t==NULL)return;postorder(t->left);postorder(t->right);cout<<t->dt;}/*后序遍历非递归*/void postorder2(TreePtr t){stack<TreePtr> s;if(!t){cout<<"empty tree"<<endl;return;}TreePtr last=t;//记录最近访问的节点s.push(t);while(!s.empty()){t=s.top();if((t->left==NULL&&t->right==NULL)||(t->right==NULL&&last==t->left)||(last==t->right)){//注意这里的第三个条件不需要判断左孩子,因为左孩子肯定先于右孩子被访问cout<<t->dt;last=t;s.pop();}else{if(t->right)s.push(t->right);if(t->left)s.push(t->left);}}}/*层次遍历(使用队列)*/void levelorder(TreePtr t){queue<TreePtr> q;TreePtr helper;if(!t){cout<<"empty tree"<<endl;return;}q.push(t);//enqueuewhile(!q.empty()){helper=q.front();//get the first oneq.pop();cout<<helper->dt;//visit itif(helper->left)q.push(helper->left);if(helper->right)q.push(helper->right);}}int main(){TreePtr t=create_tree();//前序:cout<<"preorder traversal:"<<endl;cout<<"recursive version:"<<endl;preorder(t);cout<<endl;cout<<"iterative version:"<<endl;preorder2(t);cout<<endl<<endl;//中序:cout<<"inorder traversal:"<<endl;cout<<"recursive version:"<<endl;inorder(t);cout<<endl;cout<<"iterative version:"<<endl;inorder2(t);cout<<endl<<endl;//后序:cout<<"postorder traversal:"<<endl;cout<<"recursive version:"<<endl;postorder(t);cout<<endl;cout<<"iterative version:"<<endl;postorder2(t);cout<<endl<<endl;//层序:cout<<"level-order traversal:"<<endl;levelorder(t);cout<<endl;return 0;}
需要注意的是非递归遍历的实现,尤其是后序遍历,如果一个节点没有孩子,直接访问它,如果它的孩子都被访问过,直接访问它,如果它的孩子都没有被访问过,按照右、左的顺序入栈。上面的方法用了一个辅助指针来记录最近访问的节点,判断的时候,如果p没有右孩子,last等于左孩子,则t的孩子都被访问过了,同样地,如果last等于右孩子,t的孩子也都被访问过了,因为访问右孩子之前肯定要访问左孩子。

实现后序非递归还有一种做法:

我们希望按照左、右、根的顺序访问这棵树,因此希望入栈顺序最好每次都是根、右、左。对于每一个节点,如果,必须先访问它的儿子们再访问它,因此每次入栈需要首先判断它的儿子们有没有被访问过,现在把每个节点入栈两次,弹出以后再和栈顶元素比较,如果它们相等,证明这个节点的儿子们都没有被访问过,入栈。按照相似的逻辑,对每个节点都这样操作即可:

/*后序遍历非递归的另一种实现(每个节点入栈两次)*/void postorder2(TreePtr t){stack<TreePtr> s;if(!t){cout<<"empty tree"<<endl;return;}TreePtr helper=t;s.push(helper);s.push(helper);while(!s.empty()){helper=s.top();s.pop();if(!s.empty()&&helper==s.top()){if(helper->right){s.push(helper->right);s.push(helper->right);}if(helper->left){s.push(helper->left);s.push(helper->left);}}elsecout<<helper->dt;}}

⑤如何构造二叉树

经典的问题是在知道哪些条件的情况下可以唯一确定一棵二叉树?答案是中序+前序/后续中的任意一种。

例子可以参看这两篇博文:

http://blog.csdn.net/lishichengyan/article/details/77540761(后序+中序建立二叉树)

http://blog.csdn.net/lishichengyan/article/details/77542053(前序+中序建立二叉树)

⑥如何判断二叉树是否平衡

(简单,LeetCode上有题,这里略)

⑦求二叉树的高(深度)

其实就是树的深度优先搜索,可以看这两个题:

http://blog.csdn.net/lishichengyan/article/details/77542264(最大深度)

http://blog.csdn.net/lishichengyan/article/details/77542612(最小深度)

⑧求二叉树的叶节点数

⑨求二叉树的镜像

⑩判断同构

⑩①求最近公共祖先(LCA)

⑩②求二叉树的所有路径

⑩③把二叉树转化为链表

⑩④求节点间的最长距离

⑩⑤...(慢慢更,不着急=。=)


4、二叉查找树(BST)

(1)基本性质

(2)重要操作

(3)应用


5、更高级的话题

AVL树、红黑树、伸展树、B+树......等以后会慢慢讨论。。。对了,还有堆。。这些也是一个大坑啊orz会慢慢发文章来复习的。。




原创粉丝点击