icoding复习5 树 感觉难度巨大....
icoding 復習5?
1. 先序遍歷?
 已知二叉樹按照二叉鏈表方式存儲,利用棧的基本操作寫出先序遍歷非遞歸形式的算法:
 void pre_order(BiTree root);
 二叉樹的相關定義如下:
 typedef int DataType;
 typedef struct Node{
 ? ? DataType data;
 ? ? struct Node* left;
 ? ? struct Node* right;
 }BiTNode, *BiTree;
 遍歷所使用棧的相關操作如下:
 #define Stack_Size 50
 typedef BiTNode* ElemType;
 typedef struct{
 ? ? ElemType elem[Stack_Size];
 ? ? //BiTNode* ?elem[Stack_Size]
 ? ? int top;
 }Stack;
 void init_stack(Stack *S); // 初始化棧
 bool push(Stack* S, ElemType x); //x 入棧
 bool pop(Stack* S, ElemType *px); //出棧,元素保存到px所指的單元,函數返回true,棧為空時返回 false
 bool top(Stack* S, ElemType *px); //獲取棧頂元素,將其保存到px所指的單元,函數返回true,棧滿時返回 false
 bool is_empty(Stack* S); ?// 棧為空時返回 true,否則返回 false
 在遍歷過程中,pre_order函數需要調用 visit_node 函數來實現對結點的訪問,該函數聲明如下:
 void visit_node(BiTNode *node);
 #include 
 #include 
 #include "bitree.h" //請不要刪除,否則檢查不通過
大概率考原題和改編!!!!!!?
void pre_order(BiTree root){
 ?? ?if(!root) return;
 ?? ?Stack *S;
 ?? ?
 ?? ?BiTNode *p;
 ?? ?
 ?? ?init_stack(S);
 ?? ?push(S, root->data);
 ?? ?while(!is_empty(S)){
 ?? ??? ?pop(S, &p);
 ?? ??? ?visit_node(p);
 ?? ??? ?
 ?? ??? ?if(p->left)
 ?? ??? ??? ?push(S, p->left);
 ?? ??? ?if(p->right){
 ?? ??? ??? ?push(S, p->right);
 ?? ??? ?}
 ?? ?}?
 }
 //解法2, 聲明為Stack S;?
 void pre_order(BiTree root)
 {
 ? ? Stack S;
 ? ? BiTNode *p, *q;
? ? //?? ?S.top = -1; 初始化應該會賦值
 ? ? p = root;
 ? ? init_stack(&S);
? ? if (p == NULL)
 ? ? ? ? return;
 ? ? do {
 ? ? ? ? if (p) {
 ? ? ? ? ? ? visit_node(p);//先序遍歷的核心,先訪問根節點?
 ? ? ? ? ? ? push(&S, p);
 ? ? ? ? ? ? p = p->left;
 ? ? ? ? } else {
 ? ? ? ? ? ? pop(&S, &p);
 ? ? ? ? ? ? p = p->right;
 ? ? ? ? }
 ? ? } while (p || !(is_empty(&S)));
 }
//中序遍歷
 void InOrder(BiTNode *root){
 ?? ?Stack *S; BiTNode *p;
 ?? ?init_stack(S);
 ?? ?if(!root ) return;
 ?? ?while(p || !is_empty(S)){
 ?? ??? ?while(p){
 ?? ??? ??? ?push(S, p);
 ?? ??? ??? ?p = p->left;
 ?? ??? ?}
 ?? ??? ?if(!is_empty(S)){
 ?? ??? ??? ?pop(S, &p);
 ?? ??? ??? ?visit_node(p);
 ?? ??? ??? ?p = p->right;
 ?? ??? ?}
 ?? ?}
 }?
//后序遍歷非遞歸 難?
 void PostOrder(BiTNode *root){
 ?? ?Stack *S; BiTNode *p, *r; bool flag;
 ?? ?init_stack(S);
 ?? ?p = root;
 ?? ?do{
 ?? ??? ?while(p){
 ?? ??? ??? ?push(S, p);
 ?? ??? ??? ?p = p->left;
 ?? ??? ?}
 ?? ??? ?r = NULL;
 ?? ??? ?flag = true;
 ?? ??? ?
 ?? ??? ?while(!is_empty(S) && flag){
 ?? ??? ??? ?top(S, &p);
 ?? ??? ??? ?if(p->right == r){
 ?? ??? ??? ??? ?visit_node(p);
 ?? ??? ??? ??? ?pop(S, &p);
 ?? ??? ??? ??? ?r = p;
 ?? ??? ??? ?}
 ?? ??? ??? ?else{
 ?? ??? ??? ??? ?p = p->right;
 ?? ??? ??? ??? ?flag = false;
 ?? ??? ??? ?}
 ?? ??? ?}
 ?? ?}while(!is_empty(S));
 }?
2. 路徑?
 假設二叉樹采用二叉鏈表方式存儲, root指向根結點,node 指向二叉樹中的一個結點,
 編寫函數 path,計算root到 node 之間的路徑,(該路徑包括root結點和 node 結點)。path 函數聲明如下:
 bool path(BiTNode* root, BiTNode* node, Stack* s);
 其中,root指向二叉樹的根結點,node指向二叉樹中的另一結點,s 為已經初始化好的棧,
 該棧用來保存函數所計算的路徑,如正確找出路徑,則函數返回 true,此時root在棧底,node在棧頂;
#include "bitree.h" //請不要刪除,否則檢查不通過
 #include 
 #include 
bool path(BiTNode* root, BiTNode* node, Stack* s){
 ?? ?BiTNode *p, *q;
 ?? ?
 ?? ?if(!root || !node)?? ?return false;
 ?? ?p = root;
 ?? ?if(p == node){
 ?? ??? ?push(s, p);
 ?? ??? ?return true;
 ?? ?}
 ?? ?
 ?? ?while(p || !is_empty(s)){
 ?? ??? ?while(p){//先壓入再判斷?
 ?? ??? ??? ?push(s, p);
 ?? ??? ??? ?if(p == node)
 ?? ??? ??? ??? ?return true;
 ?? ??? ??? ?
 ?? ??? ??? ?p = p->left;
 ?? ??? ?}
 ?? ??? ?top(s, &p);
 ?? ??? ?if(p->right == q || p->right == NULL){
 ?? ??? ??? ?q = p;
 ?? ??? ??? ?top(s, &p);
 ?? ??? ??? ?p = NULL;
 ?? ??? ?}
 ?? ??? ?else
 ?? ??? ??? ?p = p->right;
 ?? ?}
 ?? ?return true;
 }
 3. 共同祖先
 假設二叉樹采用二叉鏈表方式存儲, root指向根結點,p所指結點和q所指結點為二叉樹中的兩個結點,
 編寫一個計算它們的最近的共同祖先,函數定義如下:
 BiTNode * nearest_ancestor(BiTree root, BiTNode *p, BiTNode *q);
 其中 root 指向二叉樹的根結點,p 和 q 分別指向二叉樹中的兩個結點。
 提示:在完成本題時,可利用 path 函數獲取p和q兩個結點到根結點之間的路徑,
 之后再計算兩條公共路徑得出最近的共同祖先。path函數及棧相關定義如下:
 #include 
 #include 
 #include "bitree.h" //請不要刪除,否則檢查不通過
BiTNode * nearest_ancestor(BiTree root, BiTNode *p, BiTNode *q){
 ?? ?if(!root || !p || !q) return NULL;
 ?? ?Stack *s1, *s2;
 ?? ?init_stack(s1); init_stack(s2);
 ?? ?path(root, p, s1);
 ?? ?path(root, q, s2);
 ?? ?for(int i = 0; s1->elem[i] == s2->elem[i]; i++)?
 ?? ??? ?;
 ?? ?return s1->elem[i-1];
 }?
4. 樹轉二叉樹
 使用隊列,編寫transfrom函數,將普通樹轉換成對應的二叉樹。二叉樹的相關定義如下:
 typedef int DataType;
 typedef struct Node{
 ? ? DataType data;
 ? ? struct Node* left;
 ? ? struct Node* right;
 }BiTNode, *BiTree;
普通樹節點 的定義如下:
 #define MAX_CHILDREN_NUM 5
 struct _CSNode
 {
 ? ? DataType data;
 ? ? struct _CSNode *children[MAX_CHILDREN_NUM];
 };
 typedef struct _CSNode CSNode;
 其中,子樹的根節點的指針存放在children數組的前k個元素中,即如果children[i]的值為NULL,
 而children[i-1]不為NULL,則表明該結點只有i棵子樹,子樹根結點分別保存在children[0]至children[i-1]中。
 隊列相關定義及操作如下:
 struct __Queue
 {
 ? ? int i, j; //指向數組內元素的游標
 ? ? void **array;//這個就是提示!!!!!!!!!!!!!!!!!!!!!!!!!!!?
 };
 typedef struct __Queue Queue;
Queue* create_queue(); //創建隊列
 bool is_empty_queue(Queue *tree); //隊為空返回true,不為空時返回false
 void* del_queue(Queue *tree); //結點指針出隊
 void add_queue(Queue *tree, void *node); //結點指針入隊
 void free_queue(Queue *tree); //釋放隊列
 transform函數定義如下:
BiTNode* transform(CSNode *root);
 其中 root 為普通樹的根結點,函數返回該樹對應二叉樹的根結點。
 #include 
 #include 
 #include "bitree.h" //請不要刪除,否則檢查不通過?
 ?
 BiTNode* transform(CSNode *root){
 ?? ?if(!root) return NULL;
 ?? ?
 ?? ?Queue *que, *bque;
 ?? ?
 ?? ?BiTNode *p;
 ?? ?//二叉樹根結點創立?
 ?? ?//小心點, 記得分配空間?
 ?? ?//為什么想到建立二叉樹結點?
 ?? ?//普通樹結點和二叉樹結點無法強制類型轉換?
 ?? ?p = (BiTNode *)malloc(sizeof(struct Node));
 ?? ?p->data = root->data;
 ?? ?p->left = p->right = NULL;
 ?? ??
 ?? ?
 ?? ?que = create_queue();
 ?? ?bque = create_queue();
 ?? ?//建立雙隊目的在于建立有序二叉結點序列?
 ?? ?add_queue(que, root);
 ?? ?add_queue(bque, p);
 ?? ?
 ?? ?//注意這個while怎么處理好孩子與孫子關系的, 沒用遞歸!!!?
 ?? ?while(!is_empty_queue(que)){
 ?? ??? ?BiTree bq;//創建二叉樹隊列頭結點(根結點)?
 ?? ??? ?bq = del_queue(bque);
 ?? ??? ?CSNode *q;
 ?? ??? ?q = del_queue(que);
 ?? ??? ?//第一次執行該操作就相當于建立了二叉樹的根
 ?? ??? ?
 ?? ??? ?int i = 0;?
 ?? ??? ?BiTNode *former = NULL;
 ?? ??? ?
 ?? ??? ?for(i = 0; i < MAX_CHILDREN_NUM; i++){
 ?? ??? ??? ?if(q->children[i]){//判存在?
 ?? ??? ??? ??? ?BiTNode *bnode = (BiTNode *)malloc(sizeof(struct Node));
 ?? ??? ??? ??? ?bnode->data = q->children[i]->data;
 ?? ??? ??? ??? ?bnode->left = bnode->right = NULL;?
 ?? ??? ?
 ?? ??? ??? ??? ?//放置結點位置
 ?? ??? ??? ??? ?if(i == 0){
 ?? ??? ??? ??? ??? ?bq->left = bnode;
 ?? ??? ??? ??? ?}
 ?? ??? ??? ??? ?else{//兄弟變為孩子了可憐?
 ?? ??? ??? ??? ??? ?former->right = bnode;
 ?? ??? ??? ??? ?}
 ?? ??? ??? ??? ?former= bnode;
 ?? ??? ??? ??? ??
 ?? ??? ??? ??? ?add_queue(bque, bnode);
 ?? ??? ??? ??? ?add_queue(que, q->children[i]);
 ?? ??? ??? ?}
 ?? ??? ?} ?? ?
 ?? ?}
 ?? ?free(que->array);
 ?? ?free(que);
 ?? ?free(bque->array);
 ?? ?free(bque);
 ?? ?
 ?? ?return p;
 }
總結
以上是生活随笔為你收集整理的icoding复习5 树 感觉难度巨大....的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: icoding复习4 数组 十字链表
- 下一篇: 有道词典例句查询更直观
