赞
踩
目录
二叉树的特点是一颗有序树,每个结点的度最大为2。从根结点开始,他的左孩子和右孩子也是一颗树的根结点,也就是这个结点的左子树和右子树
二叉树的分支有左右子树之分,而树的分支无左右子树之分。
两种特殊的二叉树:
满二叉树:深度为h且结点数为2的h次方-1的二叉树,在这种二叉树中,除最后一层全是叶子结点外,其余每一层上的各个结点都有左右孩子。
完全二叉树:深度为h,有n个结点的二叉树,当且仅当每个结点都与深度为h的满二叉树中编号从1到n的结点一一对应。满二叉树是完全二叉树的特殊形式。
完全二叉树具有的特点:
1.所有的叶子节点都在最下面两层,除最后一层外的各层组成的二叉树是一颗满二叉树
2.若某个结点有右孩子,则该结点必有左孩子
性质:
1.二叉树的第i层上的结点个数的最大值为2的i-1次方(i>=1)
2.深度为h的二叉树上的结点个数的最大值为2 的h次方-1,即深度为h的完全二叉树上的结点个数为为2 的h-1次方-1.
3.对任何一颗二叉树,若其终端结点数为n0,度为2的结点数为n2,则n0 = n2 + 1
4.含有n个结点的完全二叉树的深度为[㏒2n]+1
5.具有n个结点的完全二叉树的结点按层次编号(按从上到下。从左到右的方式连续编号),则对任一结点i有:
包括初始化以及销毁
- typedef struct Node{
- int val;
- struct Node *lchild, *rchild;
- }Node;
- typedef struct tree{
- Node *root;
- int n;
- }Tree;
- //初始化结点
- Node* GetNewNode(int val){
- Node *p = (Node*)malloc(sizeof(Node));
- p->val = val;
- p->rchild = p->rchild = NULL;
- return p;
- }
- //初始化一个树
- Tree*GetNewTree(){
- Tree*tree = (Tree*)malloc(sizeof(Tree));
- tree->n = 0;
- tree->root = NULL;
- return tree;
- }
- Node* insertNode(Node *root, int val){
- if(root == NULL)
- return GetNewNode(val);
- if(root->val == val)
- return root;
- else if(root->val > val)
- root->lchild = insertNode(root->lchild, val);
- else
- root->rchild = insertNode(root->rchild, val);
- return root;
- }
- //插入一个结点
- void insert(Tree*tree, int val){
- tree->root = insertNode(tree->root, val);
- tree->n++;
- return;
- }
- //销毁
- void clearNode(Node* node){
- if(node == NULL)
- return ;
- clearNode(node->lchild);
- clearNode(node->rchild);
- free(node);
- return ;
- }
- void clearTree(Tree*tree){
- clearNode(tree->root);
- free(tree);
- return;
- }
分为前序中序后序遍历,这个前中后都是说的根节点,然后还有层序遍历
先访问根节点,先序遍历左子树,先序遍历右子树
递归方法简单而且好理解,但是对电脑内存栈需求量大
- void p1(Node *node){
- if(node){
- cout << node->val;//先输出跟结点
- p1(node->lchild);//遍历左子树
- p1(node->rchild);//遍历右子树
- }
- }
- //先序遍历的非递归算法利用栈的性质
- void p_1(Tree *tree){
- Node *ro = tree->root;
- if(ro){
- stack<Node*>s;
- s.push(ro);//根节点入栈
- while(!s.empty()){
- while(s.top() && ro){//栈顶元素非空
- cout << s.top()->val;
- ro = ro->lchild;
- s.push(ro);
- }
- s.pop();//空结点出栈
- if(!s.empty()){
- s.pop();
- ro = ro->rchild;
- s.push(ro);
- }
- }
-
- }
- return ;
- }
二叉树遍历就借用了c++STL里面的一部分
- void p1(Node *node){
- if(node){
- p1(node->lchild);//遍历左子树
- cout << node->val;//先输出跟结点
- p1(node->rchild);//遍历右子树
- }
- }
中序遍历的非递归几乎和先序一样,会一个就相当于都会了
- void p1(Node *node){
- if(node){
- p1(node->lchild);//遍历左子树
- p1(node->rchild);//遍历右子树
- cout << node->val;//先输出跟结点
- }
- }
- //后序遍历的非递归算法利用栈的性质
- void p_1(Tree *tree){
- Node *ro = tree->root;
- if(ro){
- stack<Node*>s;
- s.push(ro);//根节点入栈
- while(!s.empty()){
- while(s.top() && ro){//遍历左子树
- //cout << s.top()->val;
- ro = ro->lchild;
- s.push(ro);
- }
- s.pop();//空结点出栈
- if(!s.empty()){//遍历右子树+
- cout << a.top()->val;
- // s.pop();
- // ro = ro->rchild;
- // s.push(ro);
- if(ro->rchild){
- s.push(ro->rchild);//右子树根节点入栈
- }
- else{//左右子树遍历结束,访问根结点
- s.pop();
- cout << ro->val;
- while(!s.top() && s.top() && ro->rchild == ro){
- //若访问的结点是其双亲结点的右孩子,则双亲出栈
- s.pop();
- cout << ro->val;
- }
- if(s.empty()){//使栈顶结点的右孩子入栈
- s.push(ro->rchild);
- }
-
- }
- }
- }
-
- }
- return ;
- }
- void level(Node *node){
- Node *p = node;
- queue<Node*> q;
- q.push(p);
- while(!q.empty()){
- q.pop();
- cout << p->val;
- if(p->lchild)
- q.push(p->lchild);
- if(p->rchild)
- q.push(p->rchild);
- }
- return;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。