二叉树是一种重要的数据结构.
二叉树是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 20 typedef 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;//根节点层次编号1 while(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; } else return 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"); else printf("root1 != root2\n"); }
参考:http://blog.csdn.net/sunmenggmail/article/details/7466635
原文地址:http://blog.csdn.net/u010498696/article/details/45619951