二叉树性质和有关操作汇总

来源:互联网 发布:java计算器加减乘除 编辑:程序博客网 时间:2024/06/05 22:36

二叉树是一种重要的数据结构. 

二叉树是n(n>=0)个结点的有限集合,该集合或为空集,或由一个根结点和两棵互不相交的,分别称为根结点的左子树和右子树的二叉树组成(递归定义)

满二叉树:对于这样的一棵二叉树,如果所有分支结点都存在左右子树,且所有叶子节点都在同一层上,称这样的二叉树为满二叉树。

完全二叉树:如果一棵具有n个结点的二叉树的结构与满二叉树的前n个结点完全相同,称之为完全二叉树。

二叉树的性质:

性质1 二叉树的第i层结点数目最多为2^(i-1) (i>=1)

性质2 深度为k的二叉树至多有2^(k-1)

性质3 对于任意一棵二叉树,叶子结点(度为0)数为n0,度为2的结点个数为n2,则有n0=n2+1. 

证明:n0+n1+n2=n1+2*n2+1 即结点数=分支数+1

二叉树存储结构

1.顺序存储结构 (可用数组表示)适用于满二叉树,完全二叉树,否则会有大量空间浪费

2链式存储结构 数据域+左右孩子指针表示 数据域+左右孩子指针表示+双亲指针表示

二叉树的数据域+左右孩子指针表示还可以推广到每个结点的孩子数至多为常数k的任意类型的树,但实际中若不是所有结点都有k个孩子,则会造成空间浪费。一种巧妙的方法用来表示孩子数任意的树-----左孩子右兄弟表示法,该方法对于任意n个结点的树,只需要O(n)的存储空间。下面以二叉树的链式存储结构: 数据域+左右孩子指针表示法为例 进行二叉树的相关操作。

#include<stdio.h>#include<malloc.h>#include<stdlib.h>#define maximum 20typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;}BTNode ;typedef BTNode *BTree;struct{int ln;//节点的层次编号BTree p;//节点指针}Qu[maximum];//输入先序序列,创建二叉树的二叉链表BTree CreateBTree(){char ch;BTree T;if((ch=getchar())=='#')return(NULL);else{T=(BTNode *)malloc(sizeof(BTNode));T->data=ch;T->lchild=CreateBTree(T->lchild);//构造左子树T->rchild=CreateBTree(T->rchild);//构造右子树return (T);}}//根据前序遍历和中序遍历构建二叉树BTree CreateTreeByPreIn(char *preorder,char *inorder,int length){BTree root;int rootIndex=0;if(0==length)return NULL;root = (BTNode *)malloc(sizeof(BTNode));root->data = *preorder;for(;rootIndex<length;rootIndex++){if(inorder[rootIndex]==*preorder)break;}root->lchild = CreateTreeByPreIn(preorder+1,inorder,rootIndex);root->rchild = CreateTreeByPreIn(preorder+rootIndex+1,inorder+rootIndex+1,length-rootIndex-1);return root;}//先序遍历void preorder(BTree root){if(root!=NULL){printf("%c",root->data);preorder(root->lchild);preorder(root->rchild);}}//先序遍历的非递归算法void preorder1(BTree root){    //BTNode *St[MaxSize],*p;BTree St[maximum],p;    int top=-1;    if(root!=NULL)    {        top++;//根结点入栈        St[top]=root;        while(top>-1)//桟不为空时循环        {            p=St[top];//退桟并访问该结点            top--;            printf("%c",p->data);            if(p->rchild!=NULL)//右孩子入桟----顺序:先右再左入栈,出栈相反            {                top++;                St[top]=p->rchild;            }            if(p->lchild!=NULL)//左孩子入桟            {                top++;                St[top]=p->lchild;            }        }        printf("\n");    }}//中序遍历void inorder(BTree root){if(root){inorder(root->lchild);printf("%c",root->data);inorder(root->rchild);}}//中序遍历的非递归算法void inorder1(BTree root){    //BTNode *St[MaxSize],*p;BTree St[maximum],p;    int top=-1;    if(root!=NULL)    {p=root;        while(top>-1||p!=NULL)//桟不为空时循环        {            while(p!=NULL)//入桟            {                top++;                St[top]=p;p=p->lchild;            }if(top>-1){p=St[top];top--;printf("%c",p->data);p=p->rchild;}        }        printf("\n");    }}//后序遍历void postorder(BTree root){if(root){postorder(root->lchild);postorder(root->rchild);printf("%c",root->data);}}//后序遍历非递归算法void postorder1(BTree root){BTree St[maximum],p;    int flag,top=-1;    if(root!=NULL)    {do{while(root!=NULL){top++;St[top]=root;root=root->lchild;}p=NULL;//p指向当前节点的前一个访问的节点flag=1;//设置b的访问标记为已访问过while(top!=-1&&flag){root=St[top];//取出当前的栈顶元素if(root->rchild==p)//右子树不存在或已被访问,访问之{printf("%c",root->data);top--;p=root;//p指向刚被访问的节点}else{root=root->rchild;flag=0;//设置未被访问的标记}}}while(top!=-1);        printf("\n");    }} //层次遍历void travelevel(BTree root){BTree Qu[maximum];int front,rear;front=rear=0;if(root!=NULL)printf("%c",root->data);rear++;Qu[rear]=root;while(rear!=front){front=(front+1)%maximum;root=Qu[front];if(root->lchild!=NULL){printf("%c",root->lchild->data);rear=(rear+1)%maximum;Qu[rear]=root->lchild;}if(root->rchild!=NULL){printf("%c",root->rchild->data);rear=(rear+1)%maximum;Qu[rear]=root->rchild;}}}//统计二叉树叶子节点个数int leaf_num(BTree root){int L,R;if(root==NULL)return 0;if(root->lchild==NULL&&root->rchild==NULL)return 1;L=leaf_num(root->lchild);R=leaf_num(root->rchild);return L+R;}//统计二叉树深度int BTheight(BTree root){int l_height,r_height;if(root==NULL)return 0;else{l_height=BTheight(root->lchild);//左子树深度+1(根节点)r_height=BTheight(root->rchild);return l_height>r_height?(l_height+1):(r_height+1);}}//统计二叉树宽度int BTwidth(BTree root){int front,rear;int num,max,i,n;front=rear=0;if(root!=NULL){rear++;Qu[rear].p=root;//根节点入队Qu[rear].ln=1;//根节点层次编号1while(front!=rear){front++;root=Qu[front].p;//队头出队num=Qu[front].ln;if(root->lchild!=NULL){rear++;Qu[rear].p=root->lchild;Qu[rear].ln=num+1;}if(root->rchild!=NULL){rear++;Qu[rear].p=root->rchild;Qu[rear].ln=num+1;}}max=0;num=1;i=1;while(i<=rear)//通过比较相同层次的节点数求数的宽度{n=0;while(i<=rear&&Qu[i].ln==num){n++;i++;}num=Qu[i].ln;if(n>max)max=n;}return max;}elsereturn 0;}//输出每个从根节点到叶子节点的路径void printArray(char a[],int len){int i;for(i=0;i<len;i++)printf("%c",a[i]);printf("\n");}void printAllPath(BTree root,char path[],int pathLen){if(root == NULL)return;path[pathLen] = root->data;pathLen++;if(root->lchild == NULL && root->rchild == NULL)printArray(path,pathLen);else{printAllPath(root->lchild,path,pathLen);printAllPath(root->rchild,path,pathLen);}} void printPaths(BTree root){char path[100];printAllPath(root,path,0);}//二叉树镜像--每个节点的左右子树都交换了的。BTree exchange2(BTree T){BTree temp;if(T){temp=T->lchild;    T->lchild=T->rchild;    T->rchild=temp;exchange2(T->lchild);exchange2(T->rchild);}return T;}//比较两棵二叉树是否相等int CompareBTree(BTree root1,BTree root2){if(root1==NULL && root2==NULL)return 1;else if((root1==NULL&&root2!=NULL)||(root2==NULL&&root1!=NULL))return 0;else if(root1->data == root2->data){if(CompareBTree(root1->lchild,root2->lchild) == 1)return CompareBTree(root1->rchild,root2->rchild);}}void main(){BTree root1,root2;//int height,width;char pre_order[6]={'A','B','D','C','E','F'};char in_order[6]={'B','D','A','E','F','C'};printf("******************************************");printf("\n按先序遍历和空节点#建立二叉树:");root1 = CreateBTree();printf("\n先序遍历-递归root1:");preorder(root1);printf("\n先序遍历-非递归root1:");preorder1(root1);printf("\n中序遍历-递归root1:");inorder(root1);printf("\n中序遍历-非递归root1:");inorder1(root1);printf("\n后序遍历-递归root1:");postorder(root1);printf("\n后序遍历-非递归root1:");postorder1(root1);printf("\n层次遍历");travelevel(root1);printf("\n二叉树高度和宽度和叶子节点个数:");printf("%d,%d,%d",BTheight(root1),BTwidth(root1),leaf_num(root1));printf("\n输出二叉树所有路径:\n");printPaths(root1);printf("\n******************************************");printf("\n按先序遍历结果和中序遍历结果建立二叉树");root2 = CreateTreeByPreIn(pre_order,in_order,6);printf("\nroot1和root2是否相等:");if(CompareBTree(root1,root2)==1)printf("root1 == root2\n");elseprintf("root1 != root2\n");}




参考:http://blog.csdn.net/sunmenggmail/article/details/7466635


1 0