二叉樹順序儲存的實現
阿新 • • 發佈:2019-01-01
在實現二叉樹的順序儲存的過程中,遇到了一些問題,現記錄如下:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100/*儲存空間初始分配量*/
#define MAX_TREE_SIZE 100/*定義樹的最大節點數*/
typedef int status;
typedef int elemtype;
typedef struct position {
int level;
int order;
} position;
typedef elemtype sqbitree[MAXSIZE];
elemtype null=0 ;/*設0表示空*/
status visit(elemtype c) {
printf("%d ",c);
return OK;
}
status initbitree(sqbitree T) {
int i=0;
for(i=0; i<MAX_TREE_SIZE; i++)
T[i]=null;/*初始化時將所有節點置為空*/
return OK;
}
/*建立二叉樹*/
status createbitree(sqbitree T) {
int i=0;
printf("請按層序輸入結點的值(整型),0表示空結點,輸999結束。結點數≤%d:\n" ,MAX_TREE_SIZE);
while(i<10) {
T[i]=i+1;
/*T[(i+1)/2-1]是T[i]的雙親節點*/
if(i&&!T[(i+1)/2-1]&&T[i]) {
printf("產生了沒有雙親節點的新節點\n");
return ERROR;
}
i++;
}
/*其餘節點置空*/
while(i<MAX_TREE_SIZE) {
T[i]=null;
i++;
}
return OK;
}
/*判斷二叉樹為空*/
status emptybitree(sqbitree T) {
if(!T[0])
return TRUE;
else
return FALSE;
}
/*求二叉樹深度*/
status depthbitree(sqbitree T) {
int i,j=-1;
/*從最後一個節點開始,找到第一個不為空的節點*/
for(i=MAX_TREE_SIZE-1; i>=0; i--)
if(T[i])
break;
i++;
do {
j++;
} while(i>=pow(2,j));
return j;
}
/*返回二叉樹的根節點*/
status root(sqbitree T,elemtype *e) {
if(emptybitree(T)) {
printf("二叉樹為空\n");
return ERROR;
} else {
*e=T[0];
return OK;
}
}
/*給二叉樹中第e層序對節點賦新值value*/
status refresh(sqbitree T,position e,elemtype value) {
/*將e轉換成陣列下標,這個公式畫出示意圖很容易就能理解*/
int i=(int)(pow(2,e.level-1)+e.order-2);
/*情況一:給葉子賦空但雙親為空,返回ERROR*/
if(!value&&!T[(i+1)/2-1])
return ERROR;
/*情況二:給雙親賦空但葉子不為空,返回ERROR*/
if(!value&&T[i*2+1]||T[i*2+2])
return ERROR;
T[i]=value;
return OK;
}
/*返回一個節點的左孩子*/
elemtype leftchild(sqbitree T,elemtype e){
int i=0;
if(!T[0])
return ERROR;
for(i=0;i<MAX_TREE_SIZE;i++){
if(T[i]==e)
return T[i*2+1];
}
return ERROR;
}
/*返回一個節點的右孩子*/
elemtype rightchild(sqbitree T,elemtype e) {
int i=0;
if(!T[0]) {
printf("空樹\n");
return null;
}
for(i=0; i<MAX_TREE_SIZE; i++) {
if(T[i]==e)
return T[i*2+2];
}
return ERROR;/*沒找到*/
}
/*返回一個節點的左兄弟,若e是T的左孩子或無左兄弟,則返回"空"*/
elemtype leftslibing(sqbitree T,elemtype e) {
int i=0;
if(!T[0]) {
printf("空樹\n");
return null;
}
for(i=0; i<MAX_TREE_SIZE; i++)
if(T[i]==e&&i%2==0)/*i為偶數,*則為右子孫,減一即可得到左兄弟*//*此外,這個地方寫i%2==0h和!i%2的結果不一樣,正在思考原因*/
return T[i-1];
return null;
}
/*回一個節點的右兄弟,若e是T的左孩子或無左兄弟,則返回"空"*/
elemtype rightslibing(sqbitree T,elemtype e) {
int i=0;
if(!T[0]) {
printf("空樹\n");
return null;
}
for(i=0; i<MAX_TREE_SIZE; i++) {
if(T[i]==e&&i%2)/*i為奇數,*則為左子孫,減一即可得到右兄弟*/
return T[i+1];
}
return null;
}
/*返回雙親*/
elemtype parent(sqbitree T,elemtype e){
int i=0;
for(i=0;i<MAX_TREE_SIZE;i++){
if(T[i]==e)
return T[(i+1)/2-1];
}
}
/*遍歷二叉樹*/
/*前序遍歷*/
status preorder(sqbitree T,int i){
visit(T[i]);/*先訪問根節點,再遞迴訪問左子樹和右子樹*/
if(T[2*i+1])
preorder(T,2*i+1);
if(T[2*i+2])
preorder(T,2*i+2);
}
status pretraverse(sqbitree T){
if(emptybitree(T))
return ERROR;
else{
preorder(T,0);/*從0開始遞迴*/
printf("\n");
}
return OK;
}
/*中序遍歷二叉樹*/
void InTraverse(sqbitree T,int e)
{
if(T[2*e+1]!=null) /* 左子樹不空 */
InTraverse(T,2*e+1);
visit(T[e]);
if(T[2*e+2]!=null) /* 右子樹不空 */
InTraverse(T,2*e+2);
}
status InOrderTraverse(sqbitree T)
{
if(!emptybitree(T)) /* 樹不空 */
InTraverse(T,0);
printf("\n");
return OK;
}
/*後序遍歷二叉樹*/
status lastorder(sqbitree T,int i){
if(T[2*i+1])
lastorder(T,2*i+1);
if(T[2*i+2])
lastorder(T,2*i+2);
visit(T[i]);
}
status lasttraverse(sqbitree T){
if(emptybitree(T))
return ERROR;
else{
lastorder(T,0);
}
printf("\n");
}
int main(void) {
status i;
position p;
elemtype e;
sqbitree T;
initbitree(T);
createbitree(T);
printf("建立二叉樹後,樹空否?%d(1:是 0:否) 樹的深度=%d\n",emptybitree(T),depthbitree(T));
printf("對二叉樹做前序遍歷:");
pretraverse(T);
printf("對二叉樹做中序遍歷:");
InOrderTraverse(T);
printf("對二叉樹做後序遍歷:");
lasttraverse(T);
e=50;
printf("修改層序為3,本層序號為2的節點的值,輸入新值為%d\n",e);
p.level=3;
p.order=2;
refresh(T,p,50);
printf("對二叉樹做前序遍歷:");
pretraverse(T);
printf("節點50的雙親為%d,左右孩子分別為%d %d,左右兄弟為%d %d\n",parent(T,e),leftchild(T,e),rightchild(T,e),leftslibing(T,e),rightslibing(T,e));
initbitree(T);
printf("清空二叉樹後,樹空否?%d(1:是 0:否) 樹的深度=%d\n",emptybitree(T),depthbitree(T));
root(T,&e);
}