用C語言實現二叉樹的結構和常用操作
阿新 • • 發佈:2019-02-14
#include<stdio.h> #include <stdlib.h> typedef float ElemType; typedef struct S_BiTNode//定義結點型別結構體 { ElemType data;//資料域 struct S_BiTNode * lchild;//左子樹 struct S_BiTNode * rchild;//右子樹 struct S_BiTNode * parent;//父結點 }BiTNode; /***********************函式定義函式定義定*****************************/ // /**統計總結點數**/ int NodeCount(BiTNode *root) { int Count=0,LCount=0,RCount=0; if(root==NULL) return 0; /*遞迴方法統計*/ LCount=NodeCount(root->lchild);//左子樹結點數 RCount=NodeCount(root->rchild);//右子樹結點數 Count=LCount+RCount+1;//左子樹+右子樹+根結點 return Count; } // /**向二叉樹中插入結點**/ void InsertIntoBitTree(BiTNode **root,ElemType data) { /*建立新結點儲存待插入的data*/ BiTNode *newNode=(BiTNode*)malloc(sizeof(BiTNode)); newNode->data=data; newNode->lchild=NULL; newNode->rchild=NULL; //考慮到 當輸入是空樹時 需要改變根結點(BiTNode *root)的值,所以這裡要求輸入根節點的地址(BiTNode **root型別) if(*root==NULL)//說明是空樹 { *root=newNode;//將新結點的指標newNode賦值給根結點的指標 (*root)->parent=NULL; (*root)->lchild=NULL; (*root)->rchild=NULL; } else if((*root)->lchild==NULL) { /*左子樹為空 則將新結點newNode的指標賦值給左子樹結點的指標*/ (*root)->lchild=newNode; (*root)->lchild->parent=*root;//左子樹的父節點為根結點 } else if((*root)->rchild==NULL) { /*右子樹為空 則將新結點newNode的指標賦值給右子樹結點的指標*/ (*root)->rchild=newNode; (*root)->rchild->parent=*root;//右子樹的父節點為根結點 } /*如果根節點、左右子樹都不為空 遞歸向左子樹插入data*/ /*這樣構造的樹的特點是:根結點的右子樹只有一個結點*/ else InsertIntoBitTree(&((*root)->lchild),data); } // /*向二叉樹中有序插入資料滿足:根結點的資料域大於左結點並且小於右結點*/ void OrderInsert(BiTNode **root,ElemType data) { /*建立新結點儲存待插入的data*/ BiTNode *newNode=(BiTNode*)malloc(sizeof(BiTNode)); newNode->data=data; newNode->lchild=NULL; newNode->rchild=NULL; //考慮到 當輸入是空樹時 需要改變根結點(BiTNode *root)的值,所以這裡要求輸入根節點的地址(BiTNode **root型別) if(*root==NULL)//說明是空樹 { *root=newNode;//將新結點的指標newNode賦值給根結點的指標 (*root)->parent=NULL; (*root)->lchild=NULL; (*root)->rchild=NULL; } else//不是空樹 { BiTNode *node=(BiTNode*)malloc(sizeof(BiTNode)); BiTNode *parent=(BiTNode*)malloc(sizeof(BiTNode)); //BiTNode *node,*parent; node=(*root); parent=(*root); while(node!=NULL) { parent=node; if(node->data==data) {printf("data to insert aleady exist");exit(-1);} if(node->data>data) node=node->lchild; else node=node->rchild; } if(data>parent->data) parent->rchild=newNode; else parent->lchild=newNode; } } // /*先序遍歷並輸出:根結點 左 右*/ void PrePrint(BiTNode *root) { if(root==NULL) { printf("invalid PrePrint"); exit(-1); } printf("%f\t",root->data); if(root->lchild!=NULL) PrePrint(root->lchild); if(root->rchild!=NULL) PrePrint(root->rchild); } // /*中序遍歷並輸出:左 根結點 右*/ void MidPrint(BiTNode *root) { if(root==NULL) { printf("invalid MidPrint"); exit(-1); } if(root->lchild!=NULL) MidPrint(root->lchild); printf("%f\t",root->data); if(root->rchild!=NULL) MidPrint(root->rchild); } // /*後續遍歷並輸出:左 右 跟結點*/ void PostPrint(BiTNode *root) { if(root==NULL) { printf("invalid MidPrint"); exit(-1); } if(root->lchild!=NULL) PostPrint(root->lchild); if(root->rchild!=NULL) PostPrint(root->rchild); printf("%f\t",root->data); } // /*統計葉子結點數*/ int LeafNodeNum(BiTNode *root) { int num=0; if((root->lchild==NULL)&&(root->rchild==NULL))//說明該結點是葉子結點 ++num; else if((root->lchild!=NULL)&&((root->rchild!=NULL)))//分別對左、右子樹遞迴操作 { num=num+LeafNodeNum(root->lchild); num=num+LeafNodeNum(root->rchild); } else if (root->lchild!=NULL)//左子樹遞迴操作 num=num+LeafNodeNum(root->lchild); else num=num+LeafNodeNum(root->rchild);//右子樹遞迴操作 return num; } // /*從左到右輸出葉子結點 返回葉子結點個數*/ int LeafNodePrint(BiTNode *root) { int num=0; BiTNode *p=root; if((p->lchild==NULL)&&(p->rchild==NULL))//說明該結點是葉子結點 { printf("%f\t",p->data); ++num; } else if((p->lchild!=NULL)&&((p->rchild!=NULL)))//分別對左、右子樹遞迴操作 { num+=LeafNodePrint(root->rchild); num+=LeafNodePrint(root->lchild); } else if( (p->lchild!=NULL)) num+=LeafNodePrint(root->lchild);//左子樹遞迴操作 else num+=LeafNodePrint(root->rchild);//右子樹遞迴操作 return num; } // /*統計高度*/ int Height(BiTNode *root) { int lh=1,rh=1; if(root==NULL) return 0; lh+=Height(root->lchild); rh+=Height(root->rchild); return lh>=rh?lh:rh; } // /*銷燬樹*/ void destory(BiTNode *root) { if((root->lchild==NULL)&&(root->rchild==NULL))//free葉子結點 free(root); else if((root->lchild!=NULL)&&((root->rchild!=NULL)))//分別對左、右子樹遞迴操作 { destory(root->lchild); destory(root->rchild); free(root);//銷燬根結點 } else if(root->lchild!=NULL)//左子樹遞迴操作 { destory(root->lchild); free(root);//銷燬根結點 } else //右子樹遞迴操作 { destory(root->rchild); free(root);//銷燬根結點 } } /*******************************************下面是主函式***********************************************/ void main() { BiTNode *MyTree=NULL;//定義根結點 初始化為空 /***向二叉樹中插入子節點***/ InsertIntoBitTree(&MyTree,1); InsertIntoBitTree(&MyTree,2); InsertIntoBitTree(&MyTree,3); InsertIntoBitTree(&MyTree,4); InsertIntoBitTree(&MyTree,5); printf("node numbers: %d\n",NodeCount(MyTree));//輸出已構造二叉樹的結點數 printf("height:%d\n",Height(MyTree));//輸出已構造二叉樹的高度 printf("PreOder Ouput:\n"); PrePrint(MyTree);//按前序訪問順序 輸出樹的結點 printf("MidOder Ouput:\n"); MidPrint(MyTree);//按中序訪問順序 輸出樹的結點 printf("PostOder Ouput:\n"); PostPrint(MyTree);//按後序訪問順序 輸出樹的結點 printf("Leaf Node %d:\n",LeafNodeNum(MyTree)); LeafNodePrint(MyTree); destory(MyTree);//釋放樹的記憶體 銷燬樹 }