树的基本知识点(未完)
来源:互联网 发布:手机通话变声软件 编辑:程序博客网 时间: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会慢慢发文章来复习的。。
- 树的基本知识点(未完)
- 树的基本知识点
- java 集合知识点(未完)
- 笔试面试经常考察的知识点收集(未完待续)
- 二叉树的基本知识点
- 二叉堆的一些基本操作(未完待续)
- android学习中知识点集合(未完)
- 一些小知识点(五)未完待续。。。
- 数据库知识点总结(未完待续)
- Jquery基本知识点的总结(一)
- 编程的基本知识点(浙大)
- 交换机的基本知识点
- 自我介绍的基本知识点
- Java基本的知识点
- 线程的基本知识点
- 数组的基本知识点
- 字符串的基本知识点
- XML的基本知识点
- SVN 安装和基本使用教程
- BZOJ 2561: 最小生成树 最小割
- 【PHP框架】之ThinkPHP
- linux的dns高速缓存
- Java 下的函数对象
- 树的基本知识点(未完)
- 工作中部分写过的css样式
- ZigBee CC2530 Z-Stack 20 广播通信
- Java 8的新特性
- HAUTOJ 1280: 诡异的迷宫
- Python,2017第一语言
- Kubernetes核心原理简单总结(一)
- CIFS文件的存储
- 循环删除List中的元素