1. 程式人生 > >資料結構 關於樹的幾個證明題及程式碼實現

資料結構 關於樹的幾個證明題及程式碼實現

一、求二叉樹的深度

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

int depth(BTNode *T){
	if(!T)
		return 0;
	
	int ldepth = depth(T->lchild);
	int rdepth = depth(T->rchild);
	
	return ldepth>rchild ? (ldepth+1) : (rdepth+1);
}

二、判斷一棵樹是否是排序二叉樹(遞迴實現)

思路是:中序遍歷排序二叉樹,遍歷序列有序

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

int preVal = MIN;		//MIN表示int變數所能表示的最小值

bool isBST(BTNode *T){
	if (!T)
		return true;
	
	bool l = isBST(T->lchild);
	
	if (preVal > T->data)
		return false;
	else
		preVal = T->data;
	
	bool r = isBST(T->rchild);
	
	return l&&r;
}

三、判斷一棵樹是否是排序二叉樹(非遞迴實現)

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

bool isBST(BTNode *T){
	BTNode* stack[NODE_NUM];
	int top = -1;
	
	while(T || top != -1){
		while(T){
			stack[++top] = T;
			t = t->lchild;
		}
		
		T = stack[top--];
		
		if (T->data > stack[top]->data)
			return false;
		
		T = stack[top--]->rchild;
	}
	
	return true;
}

四、求Haffman樹的帶權路徑長度

帶權路徑長度:樹中每個  葉子節點的權值 *該葉子節點到根節點的路徑長度(邊數)  之和

思路:採用層序遍歷,通過層數可以知道該層上的葉子節點的路徑長度

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

int method(BTNode *T){
	BTNode* Q[NODE_NUM];
	int front = 0,rear = 0,sum = 0,level,node_num;	//level為當前遍歷的層數,node_num為當前層的結點數
	
	//樹為空或者僅有一個根節點,則帶權路徑為0
	if(!T || (!T->lchild && !T->rchild))
		return 0;
	
	Q[rear++] = Q->lchild;
	Q[rear++] = Q->lchild;
	level = 2;
	node_num = 2;
	
	while(isNotEmpty(Q)){
		int num = 0;		//用來記錄下一層的結點個數
		BTNode* p;
		for(int i=0;i<node_num;i++){
			p = Q[front--];
			if (!p->lchild)
				sum += (level-1) *p->weight;
			else{
				Q[rear++] = Q->lchild;
				Q[rear++] = Q->lchild;
				num += 2;
			}
		}
		level++;
		node_num = num;
	}
	
	return sum;
}
五、用遞迴演算法判斷葉子結點的個數
typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

int count;		//結點總數

void method(BTNode *T){
	if (T){
		method(T->lchild);
		if (!T->lchild && !T->rchild)
			count++;
		method(T->rchild);
	}
}

六、判斷一棵二叉樹是否平衡

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

bool main(BTNode *T){
	int depth = 0;
	return method(T,&depth);
}

bool method(BTNode *T){
	if (!T){
		&depth = 0;
		return true;
	}
	
	//儲存每顆子樹的高度
	int ldepth,rdepth;
	bool l = method(T->lchild,*ldepth);
	bool r = method(T->rchild,*rdepth);
	
	//如果有一顆子樹不平衡,或者以當前遞迴結點為根的根樹不平衡,則返回false,只要有一個false,
	//則會一直返回false,直到退出程式
	if (!(l&&r) || (ldepth-rdepth)<-1 || (ldepth-rdepth)>1)
		return false;
	
	//根樹平衡,則算出該樹的高度
	*depth = ldepth>rdepth ? (ldepth+1) : (rdepth+1);
	return true;
		 
}

七、非遞迴演算法求二叉樹只有一個孩子的結點個數(單分支)

typedef struct BTNode BTNode{
	Elemtype data;
	struct BTNode *lchild,*rchild;
} BTNode;

bool method(BTNode *T){
	BTNode* stack[NODE_NUM];
	int top = -1,count = 0;
	
	if (!T)
		return 0;
	
	while (T || top != -1){
		while(T){
			stack[++top] = T;		//入棧
			T = T->lchild;
		}
		
		T = stack[top--];
		
		if ((!T->lchild && T->rchild) || (T->lchild && !T->rchild))
			count++;
		
		T = T->rchild;
	}
	
	return count;	 
}

八、騎士巡遊(java)

#include <stdio.h>

const int n = 8;	//棋盤的行列數
int chess[n][n];	//1代表已遍歷,0代表未遍歷
int traverse[n*n];	//存放遍歷路徑,座標(x,y)代表chess中:從上往下,從左往右的第x*8+y+1個位置
int index = 0;	
int step = n*n;	

bool move(int,int);

int main(){
	int x=0,y=1;
	
	if (move(x,y)){
		//輸出遍歷序列
		for (int i=0;i<index;++i)
			printf("%d ",traverse[i]);
		printf("\n index = %d",index);
		return 0;
	}else {
		printf("遍歷失敗!");
		return 0;
	}
	
	return 0;
}

//x,y∈[0,7]
bool move (int x,int y){
	if (chess[x][y] || x<0 || x>7 || y<0 ||y>7)
		return false;
	
	--step;
	chess[x][y] = 1;
	traverse[index++] = x*8+y+1;
	
	if (step==0)
		return true;
	
	if (move(x-1,y-2))
		return true;
	if (move(x-2,y-1))
		return true;
	if (move(x-2,y+1))
		return true;
	if (move(x-1,y+2))
		return true;
	if (move(x+1,y-2))
		return true;
	if (move(x+2,y-1))
		return true;
	if (move(x+2,y+1))
		return true;
	if (move(x+1,y+2))
		return true;
	
	return false;
}

九、證明:正則二叉樹只有奇數個定點,偶數條邊

證:由定義可知,正則二叉樹結點的度要麼為0,要麼為2,設Ni為度為i的結點個數,令結點總數為n,則有:

        N0 = N2 + 1 ,  N0 + N2 = N ,推得:2 * N2 + 1 = n,故有奇數個頂點,又邊數 = 頂點數 - 1,則有

        偶數條邊