hello,你們好,明天就是"double eleven了,不知道你們準備好沒有,咱們仍是加班加點的把二叉樹來看一下。node
在講遍歷以前,咱們首先應該瞭解一下二叉樹是怎麼創建的 數組
3 / \ 9 20 / \ 15 7
你可能會看到這樣的一顆二叉樹,那麼這顆二叉樹的根節點就是 3 ,而它的兩個孩子結點就是 9 和 20 ,在咱們創建一顆二叉樹的時候,
就算它只有一個或者沒有孩子,咱們也要把另一個或兩個孩子補上去,能夠是空格,也能夠是其餘你本身定義的特殊字符。(可是補了字符的兩個孩子就不用管了。)
看了上面,相信你對二叉樹已經有了一個印象了,讓咱們開始吧。函數
1、結構體post
typedef struct node{
elemtype data; //注意這裏的 elemtype 前面要設置成 char 類型(也就是字符串),指針
//由於咱們的二叉樹可能會是字母什麼的
struct node*lchild,*rchild; //而後構造它的兩個孩子指針,跟以前的 next 差很少,就是一個blog
//指向左邊的 next 和一個指向右邊的 next
}node,*btnode; //常規定義 node 數組名和 btnode 指針類型名遞歸
2、創建二叉樹圖片
3 / \ 9 20 / \ 15 7
關於方法,上面有提到,這裏再提兩點:字符串
1,在構造數的過程當中,由於用到的是遞歸,因此當咱們構造了 3 以後,再構造 9 時,就又能夠把它當作是一個新的跟結點,這就是咱們遞歸的原理。it
2,就是咱們的二叉樹的輸入問題了,由於存在着某些孩子結點不存在的狀況,因此在輸入的時候就要注意了,如上圖,咱們的輸入就應該是:
(咱們的表空字符設爲 * )
39**2015**7***
是的,元素之間沒有空格,咱們的輸入按照的是前序遍歷的輸入(當初滿二叉樹的前序),在沒有的地方補上表空字符 * 就行了
你們會不會問爲何 15 後面有兩個 * 呢,咱們前面提到的就算沒有可是也要補上去就是這個了,9 後面構造了兩個,而後構造的節點後面就不用管啦
#注意最後一個節點必須多輸入一個 * ,這樣計算機才知道已經輸入完了
Status creat_btree(btnode *T){
elemtype ch; //定義一下咱們即將輸入的元素
scanf("%c",&ch); //直接一次性輸入全部元素,計算機會一個
//一個讀取
if(ch == ' ') (*T) = NULL; //這裏的空格就是咱們的表空字符,當這個
//孩子不存在的時候,就能夠把它的指針
//定位 NULL 了
else{
if(!((*T) = (btnode)malloc(sizeof(node)))) exit(ERROR);
(*T)->data=ch; //空間分配成功,就能夠給咱們的結點賦值了。
creat_btree(&(*T)->lchild); //賦完值以後,利用遞歸,就能夠先構造它的
//左邊(左子樹)
creat_btree(&(*T)->rchild); //構造右子樹
}
return OK; //你們能夠試着想一下,先是跟結點,而後是它
//的孩子,當其中一個孩子的孩子的孩子......就算
//沒有的也構造完了,這個孩子就完成了,就
//經過return 返回,
//進行下一個遞歸,最後一個 return(也就是咱們
//多寫的那個 * )
//返回以後,就表明結束啦。
}
在遍歷以前,我須要先設置一個 printf 函數
Status print(elemtype e){
printf("%c ",e);
return OK;
}
3、前序遍歷
前序遍歷首先訪問根節點,而後遍歷左子樹,最後遍歷右子樹。(以下圖)
Status preorder(btnode T,Status (* print)(elemtype e)){ //你們是否是對這裏的參數感到奇怪,
//經過後面的參數。咱們就能夠在子函數
//裏面調用咱們定義了的其餘子函數了
if(T){ //先判斷根節點是否爲空
if (print(T->data)) //非空的話就能夠輸出它所表明的元素了
if(preorder(T->lchild,print)) //而後再對左邊進行遍歷,注意一下 preorder
//的函數調用方式
if(preorder(T->rchild,print)) //接着是右邊
return OK; //這個 OK 跟咱們建立二叉樹的原理是同樣的
//(其實遞歸的原理都差很少)
else return ERROR;
}
else return OK;
}
4、中序遍歷
中序遍歷是先遍歷左子樹,而後訪問根節點,而後遍歷右子樹。
Status inorder(btnode T,Status (* print)(elemtype e)){
if(T){
if(inorder(T->lchild,print))
if (print(T->data))
if(inorder(T->rchild,print))
return OK;
else return ERROR; //別的就很少說了,提一下這裏
//的 return ERROR ,這個必須是跟
//print(T->data)的 if 對齊的,爲了防止
//輸入或者輸出的時候有誤,
//用來退出錯誤項的。
}
else return OK;
}
5、後序遍歷
後序遍歷是先遍歷左子樹,而後遍歷右子樹,最後訪問樹的根節點。
Status postorder(btnode T,Status (* print)(elemtype e)){
if(T){
if(postorder(T->lchild,print))
if(postorder(T->rchild,print))
if (print(T->data))
return OK;}
else return ERROR;
else return OK;
}
差很少就很少說了。
附:main函數
void main()
{
node t;btnode T = &t; //這裏記住要指一下。
creat_btree(&T);
printf("前序遍歷爲:");preorder(T,print);
printf("\n中序遍歷爲:");inorder(T,print);
printf("\n後序遍歷爲:");postorder(T,print);
system("pause");
}
全部圖片來自LeetCode