家譜構建第一步,就是要理解記憶體。樹實際上就是乙個多叉鍊錶,乙個資料域,幾個指向跟自己有關係的元素的指標域,就
構成了樹的結點。而要建立鍊錶,把乙個乙個結點賦值,就要傳指向它們的指標bitree了,這樣才能修改結點的值。因為通過
子函式來建立一棵樹,每開闢乙個新節點,就malloc動態申請一塊記憶體區域,這塊區域在堆區,子函式結束時不會銷毀。
但在主函式裡定義一棵樹,一定要把樹的位址傳到子函式裡,這樣才能修改即給樹新增結點建立一棵樹,在子函式裡給樹的
根節點(*t)動態申請一塊記憶體,把輸入的值賦過去,就構造好了根節點。而之後的結點,就通過不斷地malloc構造新節點,
然後利用結點的各種指標域,賦值,把它們連線起來。連線的過程用到的是在子函式裡定義的臨時bitree指標變數,只是通過
它們實現鏈結。而我們剛開始已經抓住了「繩子的頭」(*t),就可以把樹直接拿來操作啦。
理解了子函式的引數型別,就剩下思路了。剛開始我沒有父親節點,幾個子函式勉強寫出了,可是到刪除某人的時候實在做不
下去了,後來加上父親節點發現再縷思路的時候真是得心應手。歷時三天半,我的第一棵樹終於告一段落啦。
這裡關鍵是建樹和遍歷,完成這兩部分,基本就算寫完了。建樹,家譜要用層序建樹,這裡用到佇列,利用它先進先出的排隊
性質,從根節點開始,每一層從左到右遍歷著賦值,先根節點入佇列,用乙個bitree型別的變數接收根節點出佇列,迴圈從此
展開,手動判斷有無孩子,若有,連到lchild域,判斷有沒有孩子也是乙個迴圈,設定乙個標誌,若一直有,則迴圈把新孩子
尾插到rsib兄弟結點,同時當把新結點連到舊結點的時候,新節點入佇列,直到輸入不再有孩子。這時候第乙個入佇列的節點
即左孩子出佇列,重複以上先判斷有無左孩子,把孩子們鏈結到上乙個對應結點併入佇列的過程,佇列實現了每一層從左到右
的順序插入,遍歷,實現了層序。
然後,插入刪除增加查詢,查詢時可以公升級到查出乙個人連帶他的祖宗們兄弟們兒子們,還有問有沒有孩子的時候,記得把當前
結點的名字列印出來,更只能人性化一點。
查詢,在遍歷的基礎上,找到這個人,若是祖先,只列印兒子們;若不是,利用父親指標找到父親,迴圈找到祖宗,再找兄弟,
兩種情況,若是父親的左孩子,依次列印右兄弟,若不是左孩子,則從左孩子開始依次列印父親的孩子,通過判斷跳過本身。
再找兒子,依次遍歷列印。
增加兒子,在遍歷的基礎上,找到要增加兒子的父親節點,若沒有左孩子,。。。若有左孩子,尾插。
增加兄弟,在遍歷的基礎上,找到要增加兄弟的節點,新節點尾插到最後那個兄弟的右兄弟域。
刪除兒子,在遍歷的基礎上,找到要刪除的兒子指標,若本身是父親左孩子,,,,若不是,,,,。
刪除兄弟,在遍歷的基礎上,找到要刪除的兄弟結點,若是父親左孩子,,,,若不是,,,,。
刪除某個人,在遍歷的基礎上,找到要刪除的結點,若是祖宗,,,若是父親左孩子,,,若不是,,,。
注意刪除某個人要把他的子子孫孫都刪掉。
刪除新增操作都要改變一棵樹,所以需要傳樹的位址,二級指標。把樹的根節點位址傳進去,中間的臨時變數不用設為指標型別。
free()括號裡是指標變數,銷毀指向部分的記憶體。
釋放一棵子樹的時候,要提前把它的右兄弟置為null,否則無法通過後序遍歷釋放節點空間。
主函式:
#include#include"bitree.h"
int main(void)
printf("what you want to do!\n");
c=getchar();
getchar();
} return 0;
}分檔案:
bitree.h
#ifndef bitree_h
#define bitree_h
typedef char elemtype;
typedef struct bitreenode
bitnode,*bitree;
void createbitree(bitree *t);
void levelordertree(bitree t);
void preordertree(bitree t);
int inquire(bitree t,char ch);
void postorderfree(bitree *t);
void delete_son(bitree *t,char ch_d,char ch_s);
void add_sib(bitree *t,char ch,char ch_s);
void add_son(bitree *t,char ch_d,char ch_s);
void delete_sib(bitree *t,char ch,char ch_s);
void delete_someone(bitree *t,char ch);
#endif
bitree.cpp
#include#include#include"bitree.h"
#include"queue.h"
void createbitree(bitree *t)
else
printf("%c還有孩子嗎?1 or 0 \n",x->ch);
scanf("%d",&j);
getchar();
} }}void preordertree(bitree t)
void levelordertree(bitree t)
while(!is_empty(&q))
}} printf("\n");
}
int inquire(bitree t,char ch)
while(!is_empty(&q))
}else
printf("\n");
q=(x->dad)->lchild;
printf("his sibs are: ");
if(q->ch==ch)
}else
}printf("\n");
}if(x->lchild)
}printf("\n");
} if(x->lchild)
}} return 0;
}void postorderfree(bitree *t)
void delete_son(bitree *t,char ch_d,char ch_s)
while(!is_empty(&q))
else
q=q->rsib;}}
} if(x->lchild)
}} printf("\n");
}void add_sib(bitree *t,char ch,char ch_s)
while(!is_empty(&q))
if(x->lchild)
} }}
void add_son(bitree *t,char ch_d,char ch_s)
while(!is_empty(&q))
else
if(x->lchild)
}} }
}void delete_sib(bitree *t,char ch,char ch_s)
while(!is_empty(&q))
else
p=p->rsib;}}
}if(x->lchild)
}} printf("wrong name!\n");
} /*
void delete_someone(bitree t,char ch)
preordertree(t->lchild);
preordertree(t->rsib);}*/
void delete_someone(bitree *t,char ch)
if(*t)
while(!is_empty(&q))
else
p=p->rsib;}}
} if(x->lchild)
} }}
queue.h
#ifndef queue_h
#define queue_h
#define maxqsize 100
#include"bitree.h"
typedef struct queue
queue,*pqueue;
void initqueue(pqueue p);
int is_empty(pqueue p);
int is_full(pqueue p);
void enqueue(pqueue p,bitree x);
bitree dequeue(pqueue p);
#endif
queue.cpp
#include#include"queue.h"
void initqueue(pqueue p)
int is_empty(pqueue p)
int is_full(pqueue p)
void enqueue(pqueue p,bitree x)
bitree dequeue(pqueue p)
我是一棵「樹」
我是一顆樹,之前我們資料結構家族中的乙個小朋友 棧 已經給你們介紹過的我們這個家族了 我是乙個 棧 之所以叫棧為小朋友,是因為我和他的爸爸 陣列是平輩的。之所以存在我們這樣乙個家庭,最主要的原因是陣列他們家庭雖然很強大,但是有一定的侷限性。大家都知道,無論是陣列 鍊錶以及他們家的那幾個小娃娃 棧 佇...
一棵樹是否為另一棵樹的子結構
輸入兩顆二叉樹a,b,判斷b是不是a的子結構。問題描述 給定兩個二叉樹的根節點,判斷第二樹是否是第乙個樹的子樹,如果是返回1,否則返回0.拿第二個樹的每個節點去和第乙個樹做匹配,如果某個節點匹配成功,就接著往下匹配,否則重新從第二個樹的的根節點開始。注意區別 測試用例 樹1 42 6 1 3 5 7...
如何判斷一棵樹是不是另一棵樹的子樹
package suanfatest class treenode treenode int value treenode int value,treenode leftchild,treenode rightchild public int getvalue public void setvalu...