目錄
3.編寫后序遍歷二叉樹的非遞歸算法
?4.試給出二叉樹的自下而上、自右到左的層次遍歷算法 (有圖解代碼詳解)c語言代碼實現
5.假設二叉樹采用二叉鏈表存儲結構,設計一個非遞歸算法求二叉樹的高度。
?編輯
?6.設一棵二叉樹中各結點的值互不相同,其先序遍歷序列和中序遍歷序列分別存于兩個一維數組A[l...n]和 B[l...n]中,試編寫算法建立該二叉樹的二叉鏈表。
?7.二叉樹按二叉鏈表形式存儲,寫一個判別給定二叉樹是否是完全二叉樹的算法
3.編寫后序遍歷二叉樹的非遞歸算法
?本題代碼如下
void postorder(tree* t)
{struct treenode* stack[100];//初始化結構體數組int top = -1;//讓棧頂指向-1treenode* p = *t;while (p || top != -1)//p不為空,并且棧不為空{if (p){top++;//p不為空,將p壓入棧中stack[top] = p;p = p->lchild;//一直向左下遍歷}else{p = stack[top];//p等于棧頂元素if (p->rchild && p->rchild->tag == 0)//右孩子不為空且未被訪問過p = p->rchild;else//否則彈出結點并訪問{p = stack[top];top--;printf("%c", p->data);p->tag = 1;//標記p被訪問過p = NULL;}}}
}
完整測試代碼
#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;int tag;
}treenode,*tree;
void buildtree(tree *t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->tag = 0;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
void postorder(tree* t)
{struct treenode* stack[100];//初始化結構體數組int top = -1;//讓棧頂指向-1treenode* p = *t;while (p || top != -1)//p不為空,并且棧不為空{if (p){top++;//p不為空,將p壓入棧中stack[top] = p;p = p->lchild;//一直向左下遍歷}else{p = stack[top];//p等于棧頂元素if (p->rchild && p->rchild->tag == 0)//右孩子不為空且未被訪問過p = p->rchild;else//否則彈出結點并訪問{p = stack[top];top--;printf("%c", p->data);p->tag = 1;//標記p被訪問過p = NULL;}}}
}
int main()
{tree t;buildtree(&t);postorder(&t);return 0;
}
用ABD##E##CF##G##
/*?? ??? ?A
?? ?B?? ??? ?C
D?? ? ?E ? F ? ? G?? ?
*/
?4.試給出二叉樹的自下而上、自右到左的層次遍歷算法 (有圖解代碼詳解)c語言代碼實現
?本題我們采用讓結點出隊時將結點入棧,同時訪問該結點,是否有左右孩子,如果有的話,就讓左右孩子進隊。最后所有結點都入棧了,再從棧頂開始依次訪問就可以得到結果
看下面的圖解
A先入隊,然后出隊,就壓入棧中
訪問A結點,有左右孩子,左右孩子入隊
B結點出隊并入棧,并訪問B結點,B結點有左右孩子,左右孩子進隊
C結點出隊并入棧,同時訪問C結點,C結點有左右孩子,左右孩子進隊
D結點出隊并入棧,同時訪問D結點,D結點沒有左右孩子
EFG依次出隊進棧(與D的步驟相同)
最后我們看一下棧中的元素
我們讓棧中元素依次出棧就能得到我們想要的結果
下面我們來看一下代碼該如何實現:
void level(tree* t)
{treenode* q[10];treenode* s[10];int top = -1;int f = -1;int r = -1;treenode* p;q[++r] = *t;//根結點進隊while (f < r){p = q[++f];//結點出隊s[++top] = p;//結點進棧if (p->lchild)//出隊結點是否有左孩子q[++r] = p->lchild;//有左孩子,左孩子進棧if (p->rchild)//出隊結點是否有右孩子q[++r] = p->rchild;//有右孩子,右孩子進棧}while (top != -1)//依次輸出棧中元素{printf("%c ", s[top--]->data);}
}
完整測試代碼如下
#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
}treenode,*tree;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
void level(tree* t)
{treenode* q[10];treenode* s[10];int top = -1;int f = -1;int r = -1;treenode* p;q[++r] = *t;while (f < r){p = q[++f];s[++top] = p;if (p->lchild)q[++r] = p->lchild;if (p->rchild)q[++r] = p->rchild;}while (top != -1){printf("%c ", s[top--]->data);}
}
int main()
{tree t;buildtree(&t);level(&t);return 0;
}
用ABD##E##CF##G##測試
5.假設二叉樹采用二叉鏈表存儲結構,設計一個非遞歸算法求二叉樹的高度。
?采用層次遍歷的算法,設置變量 ans記錄當前結點所在的層數,設置變量 l?指向當前層的最右結點,每次層次遍歷出隊時與 l指針比較,若兩者相等,則層數加 1,并讓 l指向下一層的最右結點,直到遍歷完成。ans的值即為二又樹的高度。
本題代碼如下
int deep(tree* t)//求樹的深度
{if ((*t) == NULL)return 0; treenode* q[10];int f = -1, r = -1;//f頭結點,r尾結點int l = 0, ans = 0;//l每次指向每層的最后一個結點q[++r] = *t;treenode* p;while (f < r){p = q[++f];//隊列元素出隊,正在訪問的結點if (p->lchild)q[++r] = p->lchild;//左孩子入隊if (p->rchild)q[++r] = p->rchild;//右孩子入隊if (f == l)//處理該層的最右結點{ans++;//層數+1l = r;//讓l指向下一層}}return ans;
}
完整測試代碼
#include<stdio.h>
#include<stdlib.h>
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
}treenode, * tree;
void buildtree(tree* t)//建樹
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
int deep(tree* t)//求樹的深度
{if ((*t) == NULL)return 0; treenode* q[10];int f = -1, r = -1;//f頭結點,r尾結點int l = 0, ans = 0;//l每次指向每層的最后一個結點q[++r] = *t;treenode* p;while (f < r){p = q[++f];//隊列元素出隊,正在訪問的結點if (p->lchild)q[++r] = p->lchild;//左孩子入隊if (p->rchild)q[++r] = p->rchild;//右孩子入隊if (f == l)//處理該層的最右結點{ans++;//層數+1l = r;//讓l指向下一層}}return ans;
}
int main()
{tree t;buildtree(&t);printf("樹的高度為:%d\n", deep(&t)); return 0;
}
/* AB CD E F */
//ABD##E##CF###
?6.設一棵二叉樹中各結點的值互不相同,其先序遍歷序列和中序遍歷序列分別存于兩個一維數組A[l...n]和 B[l...n]中,試編寫算法建立該二叉樹的二叉鏈表。
?本題代碼如下
tree build(char a[], char b[], int s, int e)
{if (s <= e){treenode* root = (treenode*)malloc(sizeof(treenode));root->data = a[pos];//將子樹的根節點賦值給rootint i;for (i = s; i <= e; i++)//在b數組中找到根節點if (b[i] == root->data)break;pos++;root->lchild = build(a, b, s, i - 1);//建立左子樹root->rchild = build(a, b, i + 1, e);//建立右子樹return root;}return NULL;
}
完整測試代碼
#include<stdio.h>
typedef struct treenode {char data;struct treenode* lchild, * rchild;
}treenode,*tree;
int pos = 0;//全局變量pos
tree build(char a[], char b[], int s, int e)
{if (s <= e){treenode* root = (treenode*)malloc(sizeof(treenode));root->data = a[pos];//將子樹的根節點賦值給rootint i;for (i = s; i <= e; i++)//在b數組中找到根節點if (b[i] == root->data)break;pos++;root->lchild = build(a, b, s, i - 1);//建立左子樹root->rchild = build(a, b, i + 1, e);//建立右子樹return root;}return NULL;
}
void disp(tree t)
{if (t){disp(t->lchild);disp(t->rchild);printf("%c", t->data);}
}
int main(){char a[] = {'A','B','D','E','C','F'};//先序char b[] = {'D','B','E','A','F','C' };//中序tree root = build(a, b, 0, 5);printf("后序序列為:");disp(root);return 0;
}
?7.二叉樹按二叉鏈表形式存儲,寫一個判別給定二叉樹是否是完全二叉樹的算法
?采用層次遍歷算法,將所有結點加入隊列(包括空結點)。
如果沒有左孩子,就看有沒有右孩子,如果有右孩子,那么不為完全二叉樹。
如果有左孩子,且之前不存在缺孩子的結點,左孩子進隊,如果有右孩子,右孩子也進隊,否則就是缺孩子了。之前存在缺孩子的,那么就不是完全二叉樹。
有兩種代碼的寫法
本題代碼如下
int isok(tree* t)//判斷完全二叉樹
{squene q;q.f = q.r = q.tag = 0;int flag = false; // 標志是否遇到了空節點if (*t == NULL)return true; // 空樹也是完全二叉樹enquene(&q, *t);treenode* p;while (!isempty(&q)){dequene(&q, &p);if (p->lchild){if (flag) // 如果之前遇到了空節點,說明不是完全二叉樹return false;enquene(&q, p->lchild);}else{flag = true;}if (p->rchild){if (flag) // 如果之前遇到了空節點,說明不是完全二叉樹return false;enquene(&q, p->rchild);}else{flag = true;}}return true;
}
完整測試代碼
#include <stdio.h>
#include <stdlib.h>
#define Max 15
#define true 1
#define false 0
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
} treenode, * tree;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}
typedef struct squene
{struct treenode* data[Max];int f, r, tag;
} squene;
int isempty(squene* q)//判斷隊空
{if (q->f == q->r && q->tag == 0)return true;return false;
}
int isfull(squene* q)//判斷隊滿
{if (q->f == q->r && q->tag == 1)return true;return false;
}
int enquene(squene* q, treenode* p)//進隊操作
{if (isfull(q))return false;q->data[q->r] = p;q->r = (q->r + 1) % Max;q->tag = 1;return true;
}
int dequene(squene* q, treenode** p)//出隊操作
{if (isempty(q))return false;*p = q->data[q->f];q->f = (q->f + 1) % Max;q->tag = 0;return true;
}
int isok(tree* t)//判斷完全二叉樹
{squene q;q.f = q.r = q.tag = 0;int flag = false; // 標志是否遇到了空節點if (*t == NULL)return true; // 空樹也是完全二叉樹enquene(&q, *t);treenode* p;while (!isempty(&q)){dequene(&q, &p);if (p->lchild){if (flag) // 如果之前遇到了空節點,說明不是完全二叉樹return false;enquene(&q, p->lchild);}else{flag = true;}if (p->rchild){if (flag) // 如果之前遇到了空節點,說明不是完全二叉樹return false;enquene(&q, p->rchild);}else{flag = true;}}return true;
}
int main()
{treenode* t;buildtree(&t);if (isok(&t))printf("yes");elseprintf("no");return 0;
}
用ABD##E##CF##G##測試
/*? ? ? ? ? ? ? ? A
? ? ? ? B? ? ? ? ? ? ? ? C
D? ? ? ? E? ? ? ? F? ? ? ? G? ? ??
*/
用ABD###CF##G##測試
/*? ? ? ? ? ? ? ? A
? ? ? ? B? ? ? ? ? ? ? ? C
D? ? ? ? ? ? ? ? ? F? ? ? ? G
*/
還可以用另外一種寫法
#include <stdio.h>
#include <stdlib.h>
#define Max 15
typedef struct treenode
{char data;struct treenode* lchild, * rchild;
} treenode, * tree;
void buildtree(tree* t)
{char ch;ch = getchar();if (ch == '#')*t = NULL;else{*t = (treenode*)malloc(sizeof(treenode));(*t)->data = ch;(*t)->lchild = NULL;(*t)->rchild = NULL;buildtree(&(*t)->lchild);buildtree(&(*t)->rchild);}
}int isok(tree* t)//判斷完全二叉樹
{treenode* q[Max];int f = -1, r = -1;int tag = 1;//標記是否為完全二叉樹q[++r] = *t;treenode* p;int flag = 1;//標記缺孩子if (*t == NULL) {tag = 1;}if (!(*t)->lchild && !(*t)->rchild)tag = 1;while (f < r) {p = q[++f];if (!p->lchild) //沒有左孩子缺孩子{flag = 0;if (p->rchild)tag = 0;}else//有左孩子{if (flag)//之前不存在缺孩子的結點{q[++r] = p->lchild;if (p->rchild)q[++r] = p->rchild;elseflag = 0;}else//之前存在缺孩子的結點tag = 0;}}if (tag)return 1;return 0;
}
int main()
{treenode* t;buildtree(&t);if (isok(&t))printf("yes");elseprintf("no");return 0;
}
用ABD##E##CF##G##
/*? ? ? ? ? ? ? ? A
? ? ? ? B? ? ? ? ? ? ? ? C
D? ? ? ? E? ? ? ? F? ? ? ? G? ? ??
*/
測試結果為
用AB#E##CF###
/*? ? ? ? ? ? ? ? A
? ? ? ? B? ? ? ? ? ? ? ? C
? ? ? ? ? ? E? ? ? ? F? ?
*/
測試結果為