二叉樹以lson-rson鏈結方式儲存,以選單方式設計並完成功能任務:建立並儲存樹、輸出前序遍歷結果、輸出中序遍歷結果、輸出後序遍歷結果、交換左右子樹、統計高度,其中對於中序、後序的遍歷運算要求採用非遞迴方式。
建立二叉樹採用先序的方法建立乙個擴充二叉樹。通過遞迴的方法,先建立乙個根結點,然後再穿建立左子樹,接著是建立右子樹。
前序遍歷,(1)採用遞迴方法 先訪問根結點,在遍歷左子樹,最後遍歷右子樹。(2)採用非遞迴的方法,用乙個搜尋指標,來進行搜尋,首先搜尋指標p指向根結點,①(a)開始訪問,訪問完,(b)把p的右孩子入棧,(c)p指向p的左孩子。重複上述(a)(b)(c)三個動作直到p指向空指標。②判斷棧是否為空,不為空,則出棧,把這個值賦值給p,,然後重複①②直到棧空並且p指向空。
中序遍歷,(1)採用遞迴方法,和前序遍歷相似,只不過訪問根結點的順序變了。先遍歷左子樹,再訪問根結點,最後遍歷右子樹。(2)非遞迴的方法:這個方法也是和前序有些相似,可以參考前序的非遞迴來寫,中序是要先遍歷左子樹,才訪問根結點,最後遍歷右子樹。所以在遍歷左子樹的時候,先把根結點(包括子樹的根結點)入棧,直到搜尋指標指向空,再出棧,訪問改結點,再把搜尋指標指向該結點的右孩子。重複上述幾個動作直到棧空並且搜尋指標指向空。
後序遍歷, (2)遞迴方法 ,先遍歷左子樹,後遍歷右子樹,再訪問根結點。 (2)非遞迴方法:這個和前序、中序的非遞迴方法還是類似的,不過要多乙個標記位,來標記該結點是否能夠訪問。該標誌位可以通過乙個標誌陣列或者在二叉樹的結構體重表示,我採用標誌陣列來實現。首先搜尋指標p指向根結點,開始乙個大迴圈,迴圈的退出條件是p指向空並且棧空,①判斷p是否指向空,如果不為空,一直重複一下三個動作,將p入棧,然後標誌設為0,p指向p的左孩子。標誌陣列的下標是和該結點在棧中的次序是相對應的。當p指向空時,此時判斷棧是否為空,其結點的標識位是否為1,如果滿足這兩個條件,就執行以下兩個動作,出棧,訪問該結點。接著判斷棧是否為空,如果不是,棧頂元素的標誌位設為1,搜尋指標指向棧頂元素的右孩子。如果為空,則跳出整個大迴圈(ps:如果少了這一步,就會陷入死迴圈,因為後序遍歷,根結點最先入棧,最後被訪問,如果棧空了,說明整個樹已經遍歷結束了,需要退出迴圈)
交換左右子樹,也是採用遞迴的方法。先將根結點的左右孩子進行交換,然後把左子樹的左右孩子進行交換,最後再把右子樹的左右孩子進行交換。
統計高度,用樣也是遞迴的方法,先求左右子樹的最高值,再加上一。
源程式如下:
#include #include struct tree
;struct stack
;void menu(); //選單函式
struct tree* create(); //建立乙個二叉樹
void preorder(struct tree *t); //先序遍歷
void preorder1(struct tree *t); //遞迴先序
void preorder2(struct tree *t); //非遞迴先序
void inorder(struct tree *t); //中序遍歷
void inorder1(struct tree *t); //遞迴中序
void inorder2(struct tree *t); //非遞迴中序
void postorder(struct tree *t); //後序遍歷
void postorder1(struct tree *t); //遞迴後序
void postorder2(struct tree *t); //非遞迴後序
void exchange(struct tree *t); //交換左右子樹
void height(struct tree*t); //統計高度
int high(struct tree *t);
void quit(); //退出函式
void push(struct stack *s,struct tree *p); //入棧
struct tree* pop(struct stack *s); //出棧
struct tree* gettop(struct stack s); //獲取棧頂元素
int stackempty(struct stack s); //棧空判斷
int main()
preorder(t);break;
case 3:if(t==null)
inorder(t);break;
case 4:if(t==null)
postorder(t);break;
case 5:if(t==null)
exchange(t);break;
case 6:if(t==null)
height(t);break;
case 7:quit();break;
default:printf("輸入無效,請重新輸入:");
}menu();
scanf("%d",&choice);
}return 0;
}void menu() //選單函式
struct tree* create() //建立乙個二叉樹
return p;
}void preorder(struct tree *t) //先序遍歷
void preorder1(struct tree *t) //遞迴先序
}void preorder2(struct tree *t) //非遞迴先序
if(!stackempty(s))
}}void inorder(struct tree *t) //中序遍歷
void inorder1(struct tree *t) //遞迴中序
}void inorder2(struct tree *t) //非遞迴中序
if(!stackempty(s))
}}void postorder(struct tree *t) //後序遍歷
void postorder1(struct tree *t) //遞迴後序
}void postorder2(struct tree *t) //非遞迴後序
; while(p!=null||!stackempty(s))
while(!stackempty(s)&&flag[s.i]==1)
if(!stackempty(s))
else
break;
}}void exchange(struct tree *t) //交換左右子樹
}void height(struct tree*t) //統計高度
int high(struct tree *t)
return h;
}void quit()
void push(struct stack *s,struct tree *p) //入棧
struct tree* pop(struct stack *s) //出棧
int stackempty(struct stack s) //棧空判斷
struct tree* gettop(struct stack s) //獲取棧頂函式
總結:在建立二叉樹是建立二叉擴充樹,可以通過先序,中序,後序三種方法進行建立。前序、中序、後序的非遞迴方法中,由於是建立的二叉擴充樹,所以每個結點都當作乙個根結點來進行訪問。樹的定義是遞迴的,所以採用遞迴的方法對樹進行運算也就比較容易了。 二叉樹的遍歷 二叉樹遍歷與儲存
在資料結構中,二叉樹是非常重要的結構。例如 資料庫中經常用到b 樹結構。那麼資料庫是如何去單個查詢或者範圍查詢?首先得理解二叉樹的幾種遍歷順序 先序 中序 後序 層次遍歷。先序 根節點 左子樹 右子樹 中序 左子樹 根節點 右子樹 後序 左子樹 右子樹 根節點 按層級 class node if c...
構建二叉樹 遍歷二叉樹
陣列法構建二叉樹 public class main public static void main string args 用陣列的方式構建二叉樹 public static void createbintree 把linkedlist集合轉成二叉樹的形式 for int j 0 j 最後乙個父節...
玩轉二叉樹(二叉樹的遍歷)
時間限制 400 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 陳越 給定一棵二叉樹的中序遍歷和前序遍歷,請你先將樹做個鏡面反轉,再輸出反轉後的層序遍歷的序列。所謂鏡面反轉,是指將所有非葉結點的左右孩子對換。這裡假設鍵值都是互不相等的正整數。輸入格式 ...