二叉樹的相關操作(c語言)
二叉樹的相關操作:包括先序序列+中序序列建樹丶後序序列+中序序列建樹丶層次序列+中序序列建樹;先序遍歷丶中序遍歷丶後序遍歷丶層次遍歷;二叉樹的深度及最大寬度;度分別為0,1,2的節點個數以及總結點個數
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
//二叉樹節點結構體
struct BinaryTreeNode{
char m_key;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 定義棧的儲存表示
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
struct SqStack{
char* base;
char* top;
int stacksize;
};
// 定義佇列的儲存表示
struct QNode {
BinaryTreeNode data; //元素為一棵樹
struct QNode* next;
};
struct LinkQueue{
QNode* front;
QNode* rear;
};
// 棧的基本操作的函式
void InitStack(SqStack &S) {
S.base = (char*)malloc(STACK_INIT_SIZE * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
}
bool StackEmpty(SqStack S) {
if (S.top == S.base) return true;
else return false;
}
void Push(SqStack &S, char e) {
if (S.top - S.base >= S.stacksize) {
S.base = (char*)realloc(S.base,
(S.stacksize + STACKINCREMENT) * sizeof(char));
if (!S.base) exit(-1);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
}
void Pop(SqStack &S, char &e) {
if (S.top == S.base) exit(-1);
e = *--S.top;
}
// 佇列的基本操作的函式
void InitQueue(LinkQueue &Q) {
Q.front = Q.rear = (QNode*)malloc(sizeof(QNode));
if (!Q.front) exit(-1);
Q.front->next = NULL;
}
bool QueueEmpty(LinkQueue Q) {
if (Q.front == Q.rear) return true;
else return false;
}
void EnQueue(LinkQueue &Q, BinaryTreeNode e) {
QNode* p;
p = (QNode*)malloc(sizeof(QNode));
if (!p) exit(-1);
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
}
void DeQueue(LinkQueue &Q, BinaryTreeNode &e) {
if (Q.front == Q.rear) exit(-1);
QNode* p;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;
free(p);
}
/****************************************
func:根據前序序列和中序序列構建二叉樹
para:preOrder:前序序列;midOrder:中序序列;len:節點數
****************************************/
BinaryTreeNode* construct1(char* preOrder,char* midOrder,int len){
if(preOrder==NULL||midOrder==NULL||len<=0)
return NULL;
//先根遍歷(前序遍歷)的第一個值就是根節點的鍵值
char rootKey=preOrder[0];
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *preOrder==*midOrder)//只有一個節點
return root;
//在中根遍歷(中序遍歷)中找到根節點的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子樹節點數
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根節點,輸入錯誤
return NULL;
if(leftLen>0){ //構建左子樹
root->m_pLeft=construct1(preOrder+1,midOrder,leftLen);
}
if(len-leftLen-1>0){ //構建右子樹
root->m_pRight=construct1(preOrder+leftLen+1,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根據後序序列和中序序列構建二叉樹
para:postOrder:後序序列;midOrder:中序序列;len:節點數
****************************************/
BinaryTreeNode* construct2(char* postOrder,char* midOrder,int len)
{
if(postOrder==NULL || midOrder==NULL || len<=0)
return NULL;
//後根遍歷(後序遍歷)的最後一個值就是根節點的鍵值
char rootKey=*(postOrder+len-1); //獲取根節點的值
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
if(len==1 && *postOrder==*midOrder)//只有一個節點
return root;
//在中根遍歷(中序遍歷)中找到根節點的值
char* rootMidOrder=midOrder;
int leftLen=0; //左子樹節點數
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)){
++rootMidOrder;
++leftLen;
}
if(*rootMidOrder!=rootKey)//在中根序列未找到根節點,輸入錯誤
return NULL;
if(leftLen>0){ //構建左子樹
root->m_pLeft=construct2(postOrder,midOrder,leftLen);
}
if(len-leftLen-1>0){ //構建右子樹
root->m_pRight=construct2(postOrder+leftLen,rootMidOrder+1,len-leftLen-1);
}
return root;
}
/****************************************
func:根據後序序列和層次序列構建二叉樹
para:level:層次序列;midOrder:中序序列;root:二叉樹指標引用
****************************************/
void construct3(char* level,char* midOrder,BinaryTreeNode* &root)
{
int i;
int len=strlen(level); //取得層次遍歷長度
int pos=0;
if(len==0 || level==NULL || midOrder==NULL)
{
return;
}
char *p=strchr(midOrder,level[0]);
if(p==NULL) //如果為空則拋棄第一個,跳到下一個;
{
char *L=(char*)malloc(sizeof(char)*len); //開闢陣列
strncpy(L,level+1,len-1); //捨棄第一個
L[len-1]=0;
construct3(L,midOrder,root); //呼叫建樹函式
return ;
}
pos=p-midOrder; //得到中序遍歷左子樹字串長度
root->m_key=level[0]; //為根節點賦值
root->m_pLeft=NULL;
root->m_pRight=NULL;
if(pos!=0) //左子樹的遞迴呼叫
{
root->m_pLeft=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *left_level=(char*)malloc(sizeof(char)*len);
char *left_inor=(char*)malloc(sizeof(char)*(pos));
strncpy(left_level,level+1,len-1); //捨去層次遍歷第一個
strncpy(left_inor,midOrder,pos); //擷取左子樹字串
left_level[len-1]=0;
left_inor[pos]=0;
construct3(left_level,left_inor,root->m_pLeft);
}
if(pos < strlen(midOrder)-1) //右子樹的遞迴呼叫
{
root->m_pRight=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
char *right_level=(char*)malloc(sizeof(char)*(len));
char *right_inor=(char*)malloc(sizeof(char)*(len-pos));
strncpy(right_level,level+1,len-1);
strncpy(right_inor,midOrder+pos+1,len-pos-1);
right_level[len-1]=0;
right_inor[len-pos-1]=0;
construct3(right_level,right_inor,root->m_pRight);
}
}
//先根遞迴遍歷
void preOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
printf("%c ",root->m_key);
preOrderRecursion(root->m_pLeft);
preOrderRecursion(root->m_pRight);
}
//中根遞迴遍歷
void midOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
midOrderRecursion(root->m_pLeft);
printf("%c ",root->m_key);
midOrderRecursion(root->m_pRight);
}
//後根遞迴遍歷
void postOrderRecursion(BinaryTreeNode* root){
if(root==NULL)
return;
postOrderRecursion(root->m_pLeft);
postOrderRecursion(root->m_pRight);
printf("%c ",root->m_key);
}
//層次遍歷二叉樹,使用佇列實現
void breadthFirstOrder(BinaryTreeNode* root){
LinkQueue Q;
InitQueue(Q);
BinaryTreeNode p;
if (root)
EnQueue(Q,*root);
else
exit(-1);
while (!QueueEmpty(Q)) {
DeQueue(Q, p);
printf("%c ",p.m_key);
if (p.m_pLeft)
EnQueue(Q,*p.m_pLeft);
if (p.m_pRight)
EnQueue(Q,*p.m_pRight);
}
}
//返回二叉樹的深度
int BiTreeDepth( BinaryTreeNode* T)
{
int i,j;
if(!T)
return 0;
if(T->m_pLeft)
i=BiTreeDepth(T->m_pLeft);
else
i=0;
if(T->m_pRight)
j=BiTreeDepth(T->m_pRight);
else
j=0;
return i>j?i+1:j+1;
}
//求二叉樹的最大寬度
int LevelWidth(BinaryTreeNode* root,int level)
{
if(!root)return 0;
else
{
if(level==1)
return 1;
level=LevelWidth(root->m_pLeft,level-1)+LevelWidth(root->m_pRight,level-1);
}
return level;
}
int Width(BinaryTreeNode* root)
{
int width,i;
int w[20];
for(i=0;i<20;i++)
w[i]=0;
if(!root)
width=0;
else
{
for(i=0;i<=BiTreeDepth(root);i++)
w[i]=LevelWidth(root,i+1);
}
i=0;
while(w[i])
{
if(w[i]>width)
width=w[i];
i++;
}
return width;
}
//求度為0的節點個數
int NodeNumber_0(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if(T->m_pLeft==NULL && T->m_pRight==NULL)
{
i=1;
}
else
{
i=NodeNumber_0(T->m_pLeft) + NodeNumber_0( T->m_pRight );
}
}
return i;
}
//求度為1的節點個數
int NodeNumber_1(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if( (T->m_pLeft==NULL && T->m_pRight!=NULL) || (T->m_pLeft!=NULL && T->m_pRight==NULL))
{
i=1+NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
else
{
i=NodeNumber_1(T->m_pLeft)+NodeNumber_1(T->m_pRight);
}
}
return i;
}
//求度為2的節點個數
int NodeNumber_2(BinaryTreeNode* T)
{
int i=0;
if(T)
{
if((T->m_pLeft!=NULL)&&(T->m_pRight!=NULL))
{
i=1+NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
else
{
i= NodeNumber_2(T->m_pLeft) + NodeNumber_2(T->m_pRight);
}
}
return i;
}
int main(){
int depth;
int width;
int num0;
int num1;
int num2;
int sum;
//二叉樹1先根序列
char preOrder1[9]={'1','2','4','7','3','5','6','8'};
//二叉樹1中根序列
char midOrder1[9]={'4','7','2','1','5','3','8','6'};
//二叉樹1後根序列
char postOrder1[9]={'7','4','2','5','8','6','3','1'};
//二叉樹1層次序列
char cengOrder1[9]={'1','2','3','4','5','6','7','8'};
//二叉樹2先根序列
char preOrder2[8]={'A','B','C','D','E','G','F'};
//二叉樹2中根序列
char midOrder2[8]={'C','B','E','G','D','F','A'};
//二叉樹2後根序列
char postOrder2[8]={'C','G','E','F','D','B','A'};
//二叉樹2層次序列
char cengOrder2[8]={'A','B','C','D','E','F','G'};
//二叉樹3先根序列
char preOrder3[9]={'H','D','A','C','B','G','F','E'};
//二叉樹3中根序列
char midOrder3[9]={'A','D','C','B','H','F','E','G'};
//二叉樹3後根序列
char postOrder3[9]={'A','B','C','D','E','F','G','H'};
//二叉樹3層次序列
char cengOrder3[9]={'H','D','G','A','C','F','B','E'};
//先根序列+中根序列建樹1
printf("先根序列+中根序列建樹1\n");
BinaryTreeNode* root1=construct1(preOrder1,midOrder1,8);
//先序遍歷樹1
printf("該二叉樹的先序遍歷為:");
preOrderRecursion(root1);
printf("\n");
//中序遍歷樹1
printf("該二叉樹的中序遍歷為:");
midOrderRecursion(root1);
printf("\n");
//後序遍歷樹1
printf("該二叉樹的後序遍歷為:");
postOrderRecursion(root1);
printf("\n");
//層次遍歷樹1
printf("該二叉樹的層次遍歷為:");
breadthFirstOrder(root1);
printf("\n");
//二叉樹1的深度
depth=BiTreeDepth(root1);
printf("該二叉樹的深度為%d\n",depth);
//二叉樹1的最大寬度
width=Width(root1);
printf("該二叉樹的最大寬度為%d\n",width);
//二叉樹1度為0的節點個數
num0=NodeNumber_0(root1);
printf("該二叉樹度為0的節點個數為%d\n",num0);
//二叉樹1度為1的節點個數
num1=NodeNumber_1(root1);
printf("該二叉樹度為1的節點個數為%d\n",num1);
//二叉樹1度為2的節點個數
num2=NodeNumber_2(root1);
printf("該二叉樹度為2的節點個數為%d\n",num2);
//二叉樹1總結點個數
sum=num0+num1+num2;
printf("該二叉樹度的總節點個數為%d\n",sum);
printf("\n");
// 後根序列+中根序列建樹2
printf("後根序列+中根序列建樹2\n");
BinaryTreeNode* root2=construct2(postOrder2,midOrder2,7);
//先序遍歷樹2
printf("該二叉樹的先序遍歷為:");
preOrderRecursion(root2);
printf("\n");
//中序遍歷樹2
printf("該二叉樹的中序遍歷為:");
midOrderRecursion(root2);
printf("\n");
//後序遍歷樹2
printf("該二叉樹的後序遍歷為:");
postOrderRecursion(root2);
printf("\n");
//層次遍歷樹2
printf("該二叉樹的層次遍歷為:");
breadthFirstOrder(root2);
printf("\n");
//二叉樹2的深度
depth=BiTreeDepth(root2);
printf("該二叉樹的深度為%d\n",depth);
//二叉樹2的最大寬度
width=Width(root2);
printf("該二叉樹的最大寬度為%d\n",width);
//二叉樹2度為0的節點個數
num0=NodeNumber_0(root2);
printf("該二叉樹度為0的節點個數為%d\n",num0);
//二叉樹2度為1的節點個數
num1=NodeNumber_1(root2);
printf("該二叉樹度為1的節點個數為%d\n",num1);
//二叉樹2度為2的節點個數
num2=NodeNumber_2(root2);
printf("該二叉樹度為2的節點個數為%d\n",num2);
//二叉樹2總結點個數
sum=num0+num1+num2;
printf("該二叉樹度的總節點個數為%d\n",sum);
printf("\n");
//層次序列+中根序列建樹3
printf("層次序列+中根序列建樹3\n");
BinaryTreeNode* root3;
root3=(BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
construct3(cengOrder3,midOrder3,root3);
//先序遍歷樹3
printf("該二叉樹的先序遍歷為:");
preOrderRecursion(root3);
printf("\n");
//中序遍歷樹3
printf("該二叉樹的中序遍歷為:");
midOrderRecursion(root3);
printf("\n");
//後序遍歷樹3
printf("該二叉樹的後序遍歷為:");
postOrderRecursion(root3);
printf("\n");
//層次遍歷樹3
printf("該二叉樹的層次遍歷為:");
breadthFirstOrder(root3);
printf("\n");
//二叉樹3的深度
depth=BiTreeDepth(root3);
printf("該二叉樹的深度為%d\n",depth);
//二叉樹3的最大寬度
width=Width(root3);
printf("該二叉樹的最大寬度為%d\n",width);
//二叉樹3度為0的節點個數
num0=NodeNumber_0(root3);
printf("該二叉樹度為0的節點個數為%d\n",num0);
//二叉樹3度為1的節點個數
num1=NodeNumber_1(root3);
printf("該二叉樹度為1的節點個數為%d\n",num1);
//二叉樹3度為2的節點個數
num2=NodeNumber_2(root3);
printf("該二叉樹度為2的節點個數為%d\n",num2);
//二叉樹3總結點個數
sum=num0+num1+num2;
printf("該二叉樹度的總節點個數為%d\n",sum);
return 0;
}
執行結果