二叉樹是一種非常重要的資料結構,它是分支結構的基礎,今天本人將寫一篇部落格來敘述一下其相關的演算法以及二叉樹的建立過程。
1:二叉樹的建立:
主要有 先序,中序,後序,層序建立幾種方式,其中前三種建立在二叉樹遍曆方式的基礎上的。
(1):先序建立
先序建立就是先建立根節點,隨後依次建立其左子樹和右子樹,我們可以採用遞迴的方法來實現,因為二叉樹本身就是建立在遞迴演算法的基礎上的。
(2):中序和後序建立:
明白了前序建立二叉樹的方式,中序和後續我們也可以類比出來,所謂前中後序,就是建立根節點的順序而已。
(3):層序遍曆和建立:
:
以上圖片反映的層序遍曆的過程,層序遍曆是建立在隊列的基礎上的,首先如果一顆二叉樹非空,讓根節點入隊,如果根節點的左子樹後右子樹非空,則根節點出隊並列印它的資料域的值,左右子樹先後入隊(誰不空誰入隊),隨後就是一個遞迴的過程了。
可見層序遍曆是從上到下,從左至右的一個遍曆過程。
所以我們也可以層序建立一個二叉樹:首先建立根節點,如果根節點的左孩子和右孩子指標沒有指向虛結點,則建立左子樹和右子樹,也是通過遞迴的方式來建立的。
二叉樹代碼:
函數檔案 Bittree.c:
#include "Bittree.h"#include <stdio.h>#include <stdlib.h>#include <assert.h>tree *Creat(tree* root, tree*(*ptree)(tree *root)){root = ptree(root);return root;}tree *Tier_creat(tree* root) //層序建立二叉樹 root為根節點{tree *s = NULL;datatype data = 0;tree *Tree_arr[MAX] = { 0 }; //建立一個儲存二叉樹結點的隊列int front = 1; //front為隊列指標初值int rear = 0; //rear為隊列末尾指標初值printf("層數建立二叉樹,以-1表示虛結點,-2表示結束。\n");scanf("%d", &data);while (data != -2){s = NULL;if (data != -1){s =(tree*) malloc(sizeof(tree)* 1);s->data = data;s->Lchild = NULL;s->Rchild = NULL; }rear++;Tree_arr[rear] = s; //雙親節點入隊if (rear == 1) root = s; //如果rear為隊頭指標,則其隊列中儲存的為二叉樹的根節點else{if (Tree_arr[rear] && s) //孩子和雙親都不是虛結點{if (rear % 2 == 0) Tree_arr[front]->Lchild = s; //新節點是左孩子if (rear % 2 == 1){Tree_arr[front]->Rchild = s; //新節點是右孩子front++; //如果是此時rear指向右孩子,則出隊,下一個節點進隊}}}scanf("%d", &data); }return root;}tree *DLR_creat(tree* root) //先序建立二叉樹{printf("以-1表示指標域為空白,以-2表示結束建立過程\n");root = NULL;int data = 0;printf("請輸入資料:");scanf("%d", &data); if (data == -1)return NULL; root = (tree*)malloc(sizeof(tree)* 1);if (root == NULL) {printf("建立失敗。\n");exit(EXIT_FAILURE); } root->data = data; root->Lchild=DLR_creat(root->Lchild); root->Rchild = DLR_creat(root->Rchild); return root;}tree *LDR_creat(tree* root) //中序建立二叉樹{printf("以-1表示指標域為空白,以-2表示結束建立過程\n");root = NULL;int data = 0;printf("請輸入資料:");scanf("%d", &data);if (data == -1)return NULL;root->Lchild = DLR_creat(root->Lchild);root = (tree*)malloc(sizeof(tree)* 1);if (root == NULL){printf("建立失敗。\n");exit(EXIT_FAILURE);}root->data = data;root->Rchild = DLR_creat(root->Rchild);return root;}tree *RLD_creat(tree* root) //後序建立二叉樹{printf("以-1表示指標域為空白,以-2表示結束建立過程\n");root = NULL;int data = 0;printf("請輸入資料:");scanf("%d", &data);if (data == -1)return NULL; root->Lchild = DLR_creat(root->Lchild);root->Rchild = DLR_creat(root->Rchild);root = (tree*)malloc(sizeof(tree)* 1);if (root == NULL){printf("建立失敗。\n");exit(EXIT_FAILURE);}root->data = data;return root;}void Print_Tree(tree *root, void(*ptree)(tree *root)) //遍曆二叉樹{assert(root);if (root == NULL){printf("樹是空樹。\n");return;}else{ptree(root);printf("\n");}}void DLR_Print(tree *root) //先序遍曆二叉樹{if (root != NULL){printf("%d ", root->data); DLR_Print(root->Lchild); DLR_Print(root->Rchild);}return;}void LDR_Print(tree *root) //中序遍曆二叉樹{if (root != NULL){DLR_Print(root->Lchild);printf("%d ", root->data);DLR_Print(root->Rchild);}return;}void RLD_Print(tree *root) //後序遍曆二 叉樹{if (root != NULL){DLR_Print(root->Lchild);DLR_Print(root->Rchild);printf("%d ", root->data);}return;}void Tie_Print(tree *root) //層序遍曆二叉樹{tree* arry[MAX] = { 0 };int rear = 1;int front = 0;if (root == NULL){printf("二叉樹為空白。\n");return;}else{arry[0] = root; //如果二叉樹不為空白,根節點先入隊。while (front < rear) //迴圈條件 隊列非空{if (arry[front]){printf("%d ", arry[front]->data);arry[rear++] = arry[front]->Lchild;arry[rear++] = arry[front]->Rchild;front++;}else{front++;}}}}int Deep_tree(tree *root) //求二叉樹的深度{assert(root);int left = 0;int right = 0;int deep = 0;if (root != NULL){left=Deep_tree(root->Lchild); //求左子樹深度right = Deep_tree(root->Rchild); //求右子樹深度deep = left > right ? (left + 1) : (right + 1);}return deep;}int Node_du(tree *root) //求某個節點的度{assert(root);int ret = 0;if (root == NULL)return 0;else{if (root->Lchild != NULL)ret++;if (root->Rchild != NULL)ret++;return ret;}}int tree_Node(tree *root){assert(root);int ret = 0;if (root == NULL)return 0;if (root->Lchild == NULL&&root->Rchild == NULL) //葉子節點return 1;ret =1+ tree_Node(root->Lchild) + tree_Node(root->Rchild);return ret;}tree* search_Node(tree *root, datatype data) //尋找值為data的節點{assert(root);tree *p=NULL;if (root == NULL){printf("樹是空樹。\n");return NULL;}else{if (root->data == data)return root;if (root->Lchild != NULL){p = search_Node(root->Lchild,data);if (p != NULL)return p;}if (root->Rchild != NULL){p = search_Node(root->Rchild,data);if (p != NULL)return p;}return NULL; //沒找到返回空}}void Deal_tree(tree *root) //釋放記憶體{assert(root);if (root == NULL)return;Deal_tree(root->Lchild);Deal_tree(root->Rchild);free(root);root = NULL;} 標頭檔 Bittree.h
#ifndef __BITTREE_H__#define __BITTREE_H__#define _CRT_SECURE_NO_WARNINGS#define MAX 100typedef int datatype;typedef struct Bittree{datatype data;struct Bittree *Lchild;struct Bittree *Rchild;}tree;typedef struct{datatype Elem_data[MAX];int length;}Tree_arry;tree *Tier_creat(tree* root); //層序建立二叉樹 root為根節點tree *DLR_creat(tree* root); //先序建立二叉樹tree *LDR_creat(tree* root); //中序建立二叉樹tree *RLD_creat(tree* root); //後序建立二叉樹tree *Creat(tree* root,tree*(*ptree)(tree *root)); //建立二叉樹void Print_Tree(tree *root, void(*ptree)(tree *root)); //遍曆二叉樹void DLR_Print(tree *root); //先序遍曆二叉樹void LDR_Print(tree *root); //中序遍曆二叉樹void RLD_Print(tree *root); //後序遍曆二叉樹void Tie_Print(tree *root); //層序遍曆二叉樹int Deep_tree(tree *root); //求二叉樹的深度int Node_du(tree *root); //求某個節點的度int tree_Node(tree *root); //求樹的節點的個數tree* search_Node(tree *root, datatype data); //尋找值為data的節點void Deal_tree(tree *root); //釋放記憶體#endif __BITTREE_H__
測試檔案test.c:
#include "Bittree.h"#include <stdio.h>#include <stdlib.h>void Init(){printf("1:二叉樹的建立\n");printf("2:二叉樹的遍曆\n");printf("3:二叉樹的深度查詢\n");printf("4:二叉樹的某一個節點的度的查詢\n");printf("5:清空二叉樹\n");printf("0:退出\n");}void Init_Print(){printf("0:層序遍曆二叉樹.\n");printf("1:先序遍曆二叉樹.\n");printf("2:後序遍曆二叉樹.\n");printf("3:中序遍曆二叉樹.\n");}void Init_Creat(){printf("0:層序建立二叉樹.\n");printf("1:先序建立二叉樹.\n");printf("2:後序建立二叉樹.\n");printf("3:中序建立二叉樹.\n");}void test(){int ret;int key=0;int choose;datatype data=0;tree *root = NULL;tree *node = NULL;tree* (*Tree_C[4])(tree *root) = { 0 }; //函數指標數組存放二叉樹的建立方式void(*Tree_p[4])(tree *root) = { 0 }; //函數指標數組存放二叉樹的遍曆方式Tree_C[0] = Tier_creat;Tree_C[1] = DLR_creat;Tree_C[2] = LDR_creat;Tree_C[3] = RLD_creat;Tree_p[0] = Tie_Print;Tree_p[1] = DLR_Print;Tree_p[2] = LDR_Print;Tree_p[3] = DLR_Print;while (1){printf("請輸入你的選擇:");scanf("%d", &key);switch (key){case 0:printf("Program Over!!\n");exit(EXIT_FAILURE);break;case 1:Init_Creat();do{printf("請輸入你的選擇:");scanf("%d", &choose);} while (choose <= 0 && choose >= 3);root = Creat(root, Tree_C[choose]);break;case 2:Init_Print();do{printf("請輸入你的選擇:");scanf("%d", &choose);} while (choose <= 0 && choose >= 3);Print_Tree(root, Tree_p[choose]);break;case 3:ret = Deep_tree(root);printf("二叉樹的深度為:%d\n", ret);break;case 4:printf("請輸入你要查詢節點所儲存的資料:");scanf("%d", &data);node=search_Node(root, data);if (node == NULL){printf("你所要查詢的節點不存在。\n");exit(EXIT_FAILURE);}ret = Node_du(node);printf("資料為%d的節點的度為:%d\n",data, ret);break;case 5:Deal_tree(root);printf("清空成功。\n");break;}}}int main(){Init();test();system("pause");return 0;}
如果上述敘述有相關問題請大家能指出,本人郵箱:597995302@qq.com