☆ 二叉樹的前序儲存、行式儲存與前序遍歷
二叉樹的儲存與遍歷的方式有很多種,本文主要介紹二叉樹的鏈式儲存;
其中儲存與遍歷均採用前序序列。
****************************************************************************************************************************************
★下面給出了兩種表示型別(實際上是一樣的,均採用了二級指標來儲存節點資訊):
型別一:結構體重新命名的時候沒有使用指標形式
#include <stdio.h> #include <stdlib.h> typedef int Status; typedef char TElemType; typedef struct BiNode { TElemType data; struct BiNode *lchild, *rchild; }BiNode; void CreatBiTree(BiNode **T) //二級指標傳入節點地址的地址,不使用return帶出可以更好地儲存各個鏈之間的關係 { TElemType ch; scanf_s("%c", &ch); getchar(); //注意這裡要使用getchar()來吸收回車 if (ch == '#') { *T = NULL; } else { if (!((*T) = (BiNode *)malloc(sizeof(BiNode)))) { printf("Memory allocate error!"); exit(0); } (*T)->data = ch; CreatBiTree(&(*T)->lchild); CreatBiTree(&(*T)->rchild); } } void BiTreeTraverse(BiNode *T) { if (T == NULL) { return; } printf(">>> %c\n", T->data); BiTreeTraverse(T->lchild); BiTreeTraverse(T->rchild); } int main() { BiNode *T; system("title 二叉樹的儲存與遍歷"); printf("請按照前序連續輸入二叉樹中節點的值(一個字元)\n"); CreatBiTree(&T); //傳進指標的地址,方便直接從函式中帶出 system("pause"); BiTreeTraverse(T); printf("-END-\n"); return 0; }
型別二:結構體重新命名的時候使用指標形式
#include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR 0 typedef int Status; typedef char TElemType; typedef struct BiTNode //二叉樹的二叉連結串列節點結構 { TElemType data; struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; void CreatBiTree(BiTree *T) //使用二級指標建立二叉連結串列()二叉樹 { TElemType ch; scanf_s("%c",&ch); getchar(); //注意這裡要使用getchar()來吸收回車 if(ch=='#') { *T=NULL; } else { if(!(*T=(BiTree)malloc(sizeof(BiTNode)))) //動態分配空間 { printf("Memory allocate error!"); exit(ERROR); } (*T)->data=ch; //生成根節點 CreatBiTree(&(*T)->lchild); //構造左子樹 CreatBiTree(&(*T)->rchild); //構造右子樹 } } void PreOrderTraverse(BiTree T) { if(T==NULL) { return; } printf("%c",T->data); PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); } Status main() { BiTree T; system("title 二叉連結串列的建立與遍歷"); printf("請按照前序連續輸入二叉樹中節點的值(一個字元)\n"); CreatBiTree(&T); system("pause"); PreOrderTraverse(T); }
這裡在建立二叉樹的時候,使用的是二級指標,
使用二級指標的好處在於不用使用return就可以直接帶出自己想要的值,地址的修改會直接導致值的修改;這裡就是指標的地址被修改就會直接改變指標的值。於是就可以直接使用改變後的指標。
但是在這裡建立的時候使用二級指標比使用以及指標方便了些,具體有關二級指標的介紹以及使用可以參考另一位博主的部落格:Q點我直達Q
2018.11.11晚更新:
這裡附上一個完整的demo程式(實現前序儲存、行式儲存與前序遍歷);
1> 執行結果 (這裡的輸入表示的是兩個不同的二叉樹):
2> 原始碼: < 原始碼部分使用了C++的語句 >
這裡涉及了C++萬能標頭檔案 stdc++.h,但是在VS中並不存在該標頭檔案,可以額外下載新增;
( 對於萬能標頭檔案,在軟體DevC++中可以直接使用,而且使用的格式是#include<bits/stdc++.h>,
這裡的標頭檔案名稱為stdc++.h ,寫成bits/stdc++.h 是因為該檔案被放在了相應標頭檔案存放路徑的bits資料夾中;
我們在網上下載的標頭檔案會直接是stdc++.h,如果想直接使用,可以把標頭檔案直接放在VS相應安裝目錄下,
如下圖;如果想使用 #include<bits/stdc++.h> 的格式,在該目錄下建立一個bits資料夾,將該標頭檔案放進去即可。
檔案安裝目錄基於VS2015講解,不同的VS版本安裝目錄可能略有不同,可適當調整解決。)
#include <bits/stdc++.h>
#define R_N 7
using namespace std;
typedef int Status;
typedef char TElemType;
typedef struct BiNode
{
TElemType data;
struct BiNode *lchild, *rchild;
}BiNode;
void CreatBiTree(BiNode **T) //二級指標傳入節點地址的地址,不使用return帶出可以更好地儲存各個鏈之間的關係
{
TElemType ch;
scanf("%c", &ch);
//getchar(); //使用空格進行間隔輸入
if (ch == '#')
{
*T = NULL;
}
else
{
if (!((*T) = (BiNode *)malloc(sizeof(BiNode))))
{
printf("Memory allocate error!");
exit(0);
}
(*T)->data = ch;
CreatBiTree(&(*T)->lchild);
CreatBiTree(&(*T)->rchild);
}
}
BiNode * CreatBiNode_R(char i)
{
BiNode *p;
p = new BiNode;
if (i == '#')
{
p = NULL;
}
else
{
p->data = i;
p->lchild;
p->rchild;
}
return p;
}
BiNode * CreatBiTree_R()
{
BiNode *p[R_N] = { NULL };
cout << "Please enter the values :\n";
for (int i = 0; i < R_N; i++)
{
char value;
cin >> value;
//getchar()
p[i] = CreatBiNode_R(value);
}
for (int i = 0; i < R_N / 2; i++)
{
if (p[i] == NULL)
{
continue;
}
else
{
p[i]->lchild = p[i * 2 + 1];
p[i]->rchild = p[i * 2 + 2];
}
}
return p[0];
}
void BiTreeTraverse(BiNode *T)
{
if (T == NULL)
{
return;
}
printf(">>> %c\n", T->data);
BiTreeTraverse(T->lchild);
BiTreeTraverse(T->rchild);
}
int main()
{
BiNode *T;
system("title 二叉樹的儲存與遍歷");
printf("請按照前序連續輸入二叉樹中節點的值: \n");
CreatBiTree(&T); //傳進指標的地址,方便直接從函式中帶出
system("pause");
BiTreeTraverse(T);
printf("-END-\n");
system("pause");
printf("請按照行式連續輸入二叉樹中節點的值: \n");
BiNode *P = CreatBiTree_R();
BiTreeTraverse(P);
cout << "Traverse This BinaryTree Complete! " << endl;
return 0;
}
****************************************************************************************************************************************
最快的腳步不是跨越,而是繼續,最慢的步伐不是小步,而是徘徊。
****************************************************************************************************************************************