實現了順序存儲結構的二叉樹和隊列的基本操作,以下是相關函數及類型的聲明
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <math.h> #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define MAX_TREE_SIZE 100 #define MAX_QUEUE_SIZE 5 #define Nil ' ' typedef char TElemtype; //將樹的結點類型設置為字符型 typedef int QElemType; //將隊列的結點類型設置為整形 typedef struct{ QElemType *base; //隊列的基地址 int front; int rear; }SqQueue; typedef TElemtype SqBiTree[MAX_TREE_SIZE]; //定義順序存儲二叉樹的結構數組 typedef struct{ int level; //樹的層號 int order; //一層中的序號(從左向右) }position; /**-------隊列的函數聲明------*/ int InitQueue(SqQueue *); //初始化隊列 int DestroyQueue(SqQueue *); //銷毀隊列 int ClearQueue(SqQueue *); //清空隊列 int QueueEmpty(SqQueue *); //隊列是否為空 int GetQueueLength(SqQueue *); //獲取隊列的長度 int GetQueueHead(SqQueue *,QElemType *); //獲取隊頭元素 int EnterQueue(SqQueue *,QElemType); //向隊列中插入元素 int DeleteQueue(SqQueue *,QElemType *); //向隊列中刪除元素 int (*QueueVisit)(QElemType); //函數變量 int QueueTraverse(SqQueue *,int (*) (QElemType)); //遍歷隊列 /*---------二叉樹的函數聲明*/ int InitBiTree(SqBiTree); //初始化二叉樹 int CreateBiTree(SqBiTree); //創建二叉樹 int BiTreeEmpty(SqBiTree); //判斷二叉樹是否為空 int BiTreeDepth(SqBiTree); //計算二叉樹的深度 int GetRoot(SqBiTree,TElemtype *); //獲取二叉樹的根結點 TElemtype GetNodeValue(SqBiTree,position); //獲取二叉樹結點元素 int Assign(SqBiTree,position,TElemtype); //給結點元素賦值 TElemtype GetParent(SqBiTree,TElemtype); //獲取結點的雙親結點 TElemtype GetLeftChild(SqBiTree,TElemtype); //獲取結點的左孩子 TElemtype GetRightChild(SqBiTree,TElemtype); //獲取結點的右孩子 TElemtype GetLeftSibling(SqBiTree,TElemtype); //獲取結點的左兄弟 TElemtype GetRightSibling(SqBiTree,TElemtype); //獲取結點的右兄弟 void Move(SqBiTree,int,SqBiTree,int); //移動結點 int InsertChild(SqBiTree,TElemtype,int,SqBiTree); //插入子結點 int DeleteChild(SqBiTree,position,int); //刪除子結點 int (*TreeVisit)(TElemtype); //函數變量 int PreOrderTraverse(SqBiTree, int (*Visit)(TElemtype)); //先序遍歷二叉樹 int InOrderTraverse(SqBiTree,int (*Visit)(TElemtype)); //中序遍歷二叉樹 int PostOrderTraverse(SqBiTree,int (*Visit)(TElemtype)); //后序遍歷二叉樹 void LevelOrderTraverse(SqBiTree,int (*Visit)(TElemtype)); //層序遍歷二叉樹 void PrintTree(SqBiTree); //打印二叉樹
以下是函數的定義
*-----------隊列的函數定義-----------*/ /*初始化隊列*/ int InitQueue(SqQueue *Q) { //分配內存區域 Q->base=(QElemType *)malloc(MAX_QUEUE_SIZE*sizeof(QElemType)); if(!Q->base) { printf("存儲分配失敗.\n"); return ERROR; } Q->front=Q->rear=0; //將隊列置空 return OK; } /*銷毀隊列*/ int DestroyQueue(SqQueue *Q) { if(Q->base) { free(Q->base); } Q->front=Q->rear=0; return OK; } /*清空隊列*/ int ClearQueue(SqQueue *Q) { Q->front=Q->rear=0; return OK; } /*判斷隊列是否為空*/ int QueueEmpty(SqQueue *Q) { if(Q->front==Q->rear) { return OK; } else { return ERROR; } } /*獲取隊列長度*/ int GetQueueLength(SqQueue *Q) { return (Q->rear-Q->front); } /*獲取隊列頭的元素*/ int GetQueueHead(SqQueue *Q,QElemType *e) { if(!QueueEmpty(Q)) { *e=*(Q->base+Q->front); return OK; } return ERROR; } /*使元素進隊*/ int EnterQueue(SqQueue *Q,QElemType e) { if(Q->rear == MAX_QUEUE_SIZE) //隊列滿了,重新分配內存區域,用realloc { printf("隊列已滿,嘗試增加存儲單元...\n"); Q->base=(QElemType *)realloc(Q->base,MAX_QUEUE_SIZE+1); if(!Q->base) { printf("增加隊列存儲單元失敗.\n"); return ERROR; } } *(Q->base+Q->rear)=e; Q->rear++; return OK; } /*刪除隊頭元素*/ int DeleteQueue(SqQueue *Q,QElemType *e) { if(QueueEmpty(Q)) { //printf("隊列為空.\n"); return ERROR; } *e=*(Q->base+Q->front); Q->front++; return OK; } /*遍歷隊列*/ int QueueTraverse(SqQueue *Q,int (*QV)(QElemType) ) { int i=0; while(i<Q->rear) { (*QV)(*(Q->base+i)); i++; } } /*訪問隊列中元素的函數,將元素值打印出來*/ int QueueVisitFunc(QElemType e) { printf("%d\n",e); } /*-------二叉樹的函數定義-------*/ /*初始化樹*/ int InitBiTree(SqBiTree T) { int i; for(i=0;i<MAX_TREE_SIZE;i++) { T[i]=Nil; //將初值設為空格 } T[MAX_TREE_SIZE]='\0'; //給數組尾部加上結標致 return OK; } /*創建樹*/ int CreateBiTree(SqBiTree T) { int i=0; int l=0; char s[MAX_TREE_SIZE]; printf("請按順序輸入結點的值,空格表示空結點,結點數<=%d\n",MAX_TREE_SIZE); gets(s); l=strlen(s); for(;i<l;i++) { T[i]=s[i]; if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) { printf("出現無雙親且不是根的結點.\n"); return ERROR; } } for(;i<MAX_TREE_SIZE;i++) { T[i]=Nil; } return OK; } #define ClearBiTree InitBiTree //在順序存儲結構中,ClearBiTree和InitBiTree完全一樣 /*判斷樹是否為空*/ int BiTreeEmpty(SqBiTree T) { if(T[0]==Nil) { printf("樹為空.\n"); return TRUE; } else { return FALSE; } } /*計算樹的深度*/ int BiTreeDepth(SqBiTree T) { int j=-1; int i=0; if(BiTreeEmpty(T)) { return ERROR; } for(i=MAX_TREE_SIZE-1;i>=0;i--) { if(T[i]!=Nil) { break; } } i++; //printf("i = %d\n",i); do { j++; }while(i>=pow(2,j)); return j; } /*獲取根結點的值*/ int GetRoot(SqBiTree T,TElemtype * e) { if(BiTreeEmpty(T)) { return ERROR; } *e=T[0]; return OK; } /*根據位置獲取某一結點的值*/ TElemtype GetNodeValue(SqBiTree T,position p) { return T[(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1]; } /*根據結點的位置給某一結點元素賦值*/ int Assign(SqBiTree T,position p,TElemtype e) { int i = (int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1; if(e!=Nil&&T[(i+1)/2-1]==Nil) { printf("將要賦值的結點雙親為空,不合法.\n"); return ERROR; } if(e==Nil&&(T[2*i+1]!=Nil||T[2*i+2]!=Nil)) { printf("將有子結點的結點賦空值,不合法.\n"); return ERROR; } T[i]=e; //printf("T[%d] 已修改為: %c.\n",i,T[i]); return OK; } /*獲取結點元素的雙親結點*/ TElemtype GetParent(SqBiTree T,TElemtype e) { int i; if(BiTreeEmpty(T)) { return Nil; } for(i=0;i<MAX_TREE_SIZE;i++) { if(T[i]==e) { return T[(i+1)/2-1]; } } printf("未找到雙親結點.\n"); return Nil; } /*獲取結點元素的左孩子*/ TElemtype GetLeftChild(SqBiTree T,TElemtype e) { int i; if(BiTreeEmpty(T)) { return Nil; } for(i=0;i<MAX_TREE_SIZE;i++) { if(T[i]==e) { return T[2*i+1]; } } printf("未找到左孩子.\n"); return Nil; } /*獲取結點元素的右孩子*/ TElemtype GetRightChild(SqBiTree T,TElemtype e) { int i; if(BiTreeEmpty(T)) { return Nil; } for(i=0;i<MAX_TREE_SIZE;i++) { if(T[i]==e) { return T[2*i+2]; } } printf("未找到右孩子.\n"); return Nil; } /*獲取結點元素的左兄弟*/ TElemtype GetLeftSibling(SqBiTree T,TElemtype e) { int i; if(BiTreeEmpty(T)) { return Nil; } for(i=1;i<MAX_TREE_SIZE;i++) { if(T[i]==e&&i%2==0) { return T[i-1]; } } printf("未找到左兄弟.\n"); return Nil; } /*獲取結點元素的右兄弟*/ TElemtype GetRightSibling(SqBiTree T,TElemtype e) { int i; if(BiTreeEmpty(T)) { return Nil; } for(i=1;i<MAX_TREE_SIZE;i++) { if(T[i]==e&&i%2!=0) { return T[i+1]; } } printf("未找到右兄弟.\n"); return Nil; } /*把從T1中j結點開始的子樹移到T2中i結點開始的子樹*/ void Move(SqBiTree T1,int i1,SqBiTree T2,int i2) { if(T1[2*i1+1] != Nil) {/*左子樹不空*/ Move(T1,2*i1+1,T2,2*i2+1); } if(T1[2*i1+2] != Nil) {/*右子樹不空*/ Move(T1,2*i1+2,T2,2*i2+2); } /*左右子樹都為空,說明該結點為葉子結點,可以移動.*/ T2[i2]=T1[i1]; T1[i1]=Nil; } /*插入結點或子樹*/ int InsertChild(SqBiTree T,TElemtype e,int LR,SqBiTree S) { int j,k,i=0; if(BiTreeEmpty(T)) { return ERROR; } for(j=0;j<(int)pow(2,BiTreeDepth(T))-1;j++) { if(T[j]==e) { break; } } k=2*j+LR; //k為e結點的左或右孩子的序號 if(T[k]!=Nil) {/*e結點的左右孩子不空,即e結點不是葉子結點*/ Move(T,k,T,2*k+2); } Move(S,i,T,k); } /*刪除結點或子樹*/ int DeleteChild(SqBiTree T,position p,int LR) { int i; int k=OK; SqQueue Q; InitQueue(&Q); i=(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1; if(BiTreeEmpty(T)) { return ERROR; } i=2*i+1+LR; while(k) { if(T[2*i+1]!=Nil) { EnterQueue(&Q,2*i+1); } if(T[2*i+2]!=Nil) { EnterQueue(&Q,2*i+2); } T[i]=Nil; k=DeleteQueue(&Q,&i); } return OK; } /*訪問結點元素的函數*/ int TreeVisitFunc(TElemtype e) { printf(" %c -",e); } /*先序遍歷二叉樹的遞歸函數*/ int PreTraverse(SqBiTree T,int i) { TreeVisit(T[i]); if(T[2*i+1]!=Nil) { PreTraverse(T,2*i+1); } if(T[2*i+2]!=Nil) { PreTraverse(T,2*i+2); } } /*先序遍歷二叉樹*/ int PreOrderTraverse(SqBiTree T,int (*TV) (TElemtype e)) { TreeVisit=TV; if(BiTreeEmpty(T)) { return ERROR; } PreTraverse(T,0); } /*中序遍歷二叉樹的遞歸函數*/ int InTraverse(SqBiTree T,int i) { if(T[2*i+1]!=Nil) { InTraverse(T,2*i+1); } TreeVisit(T[i]); if(T[2*i+2]!=Nil) { InTraverse(T,2*i+2); } } /*中序遍歷二叉樹*/ int InOrderTraverse(SqBiTree T,int (*TV)(TElemtype)) { TreeVisit=TV; if(BiTreeEmpty(T)) { return ERROR; } InTraverse(T,0); } /*后序遍歷二叉樹的遞歸函數*/ int PostTraverse(SqBiTree T,int i) { if(T[2*i+1]!=Nil) { PostTraverse(T,2*i+1); } if(T[2*i+2]!=Nil) { PostTraverse(T,2*i+2); } TreeVisit(T[i]); } /*后序遍歷二叉樹*/ int PostOrderTraverse(SqBiTree T,int (*TV)(TElemtype)) { TreeVisit=TV; if(BiTreeEmpty(T)) { return ERROR; } PostTraverse(T,0); } /*打印樹*/ void PrintTree(SqBiTree T) { int j,k; position p; TElemtype e; for(j=0;j<BiTreeDepth(T);j++) { p.level=j+1; printf("第%d層:\n",p.level); for(k=0;k<pow(2,p.level-1);k++) { p.order=k+1; e=T[(int)pow(2,p.level)-1-(int)pow(2,p.level-1)+p.order-1]; printf(" %d : %c ",p.order,e); } printf("\n"); } printf("\n"); }
,最后是主函數,對以上操作的函數調用
/*程序入口函數,對二叉樹及隊列的操作的調用*/ int main() { /* SqQueue queue; InitQueue(&queue); QueueEmpty(&queue); ClearQueue(&queue); QueueEmpty(&queue); int length; length = GetQueueLength(&queue); printf("隊列長度為: %d\n",length); if(1==OK) { printf("-----------------------------\n\n"); } EnterQueue(&queue,1); EnterQueue(&queue,2); EnterQueue(&queue,3); EnterQueue(&queue,4); EnterQueue(&queue,5); QueueEmpty(&queue); length=GetQueueLength(&queue); printf("The Length of the Queue is : %d.\n",length); QElemType headElem; if(GetQueueHead(&queue,&headElem)) { printf("The Head of the Queue is : %d.\n",headElem); } QueueVisit=QueueVisitFunc; QueueTraverse(&queue,QueueVisit); printf("銷毀隊列.\n"); DestroyQueue(&queue); */ position p; SqBiTree T; SqBiTree S; int depth; int i; TElemtype elem; InitBiTree(T); BiTreeEmpty(T); CreateBiTree(T); puts(T); depth=BiTreeDepth(T); printf("The Depth of the tree is %d.\n",depth); GetRoot(T,&elem); printf("The Root of the tree is %c.\n",elem);/* printf("Please Enter the Level and Order of the Tree:\n"); scanf("%d",&p.level); scanf("%d",&p.order); fflush(stdin); elem=GetNodeValue(T,p); printf("The Node of level %d order %d is : %c \n",p.level,p.order,elem); Assign(T,p,'C');*/ printf("--------------------------------\n\n"); /* printf("輸入一個結點的值,我們可以找到其雙親,孩子和兄弟.\n"); scanf("%c",&elem); fflush(stdin); printf("%c 's parent is : %c.\n",elem,GetParent(T,elem)); printf("%c 's left child is : %c.\n",elem,GetLeftChild(T,elem)); printf("%c 's right child is : %c.\n",elem,GetRightChild(T,elem)); printf("%c 's left sibling is : %c.\n",elem,GetLeftSibling(T,elem)); printf("%c 's right sibling is : %c.\n",elem,GetRightSibling(T,elem));*/ printf("----------------------------------\n\n"); /* InitBiTree(S); CreateBiTree(S); printf("Please enter the node value where you want to insert a child.\n"); scanf("%c",&elem); InsertChild(T,elem,1,S); puts(T); printf("Please enter the node position you want to delete.\n"); scanf("%d%d",&p.level,&p.order); printf("p.level=%d,p.order=%d\n",p.level,p.order); DeleteChild(T,p,0); puts(T); */ printf("--------------遍歷二叉樹--------------------\n\n"); printf("先序遍歷:\n"); PreOrderTraverse(T,TreeVisitFunc); printf("\n中序遍歷:\n"); InOrderTraverse(T,TreeVisitFunc); printf("\n后序遍歷:\n"); PostOrderTraverse(T,TreeVisitFunc); printf("\n"); printf("--------------打印二叉樹--------------------\n\n"); PrintTree(T); }
,通過這一次的代碼實踐,更深切的體會到了二叉樹和存儲結構和邏輯結構,以后如何操作一個樹,講數據結構的書,大部分都是理論知識,只要自己實踐了,才能更好的理解.