1. 程式人生 > >【資料結構週週練】016 利用遞迴演算法及孩子兄弟表示法建立樹、遍歷樹並求樹的深度

【資料結構週週練】016 利用遞迴演算法及孩子兄弟表示法建立樹、遍歷樹並求樹的深度

一、前言

從今天起,就給大家分享一些樹的程式碼啦,不僅僅是二叉樹,我們要弄明白,普通的樹用資料結構怎麼儲存,它有哪些操作,它可以實現哪些功能?

可能大家要問了,二叉樹不是還沒有寫完嗎,線索二叉樹呢?二叉排序樹呢?平衡二叉樹呢?大家不要急,我們通過二叉樹來入門樹的演算法及程式碼實現,然後學習樹的基本操作,當大家對樹的瞭解比較深入,操作比較熟練的時候,我們再學深入的東西。

線索二叉樹可以使用建立的空指標,來加速前驅和後繼的訪問速度;

二叉排序樹是按照一定規律排序的資料儲存在樹中,例如從小到大的資料按照中序建立二叉樹即可得到二叉排序樹,二叉排序樹與後面的排序查詢演算法聯絡也比較廣泛;

平衡二叉樹是為了防止樹的高度增長過快,降低二叉排序樹的效能而設計的一種結構,要保證的是任意結點的左右子樹高度差的絕對值不超過1。

樹要比二叉樹難,二叉樹作為樹的特例,每個結點只有兩個子樹(存在或空),但是一棵普通的樹孩子數量不一定,所以在構圖過程中,沒有左右孩子之說,所以就涉及到二叉樹與最多有兩個叉的樹的區別

如下圖中,如果當成一棵普通的樹來看,編號為1的結點有一個孩子結點,畫在右側,但是這個孩子是編號1的第一個孩子結點,而不是右孩子結點。如果看作一個二叉樹,那就是編號為1的右孩子結點。這塊大家一定要注意。

首先要給大家說一下樹轉換為二叉樹,轉化規律如下:

結點左指標指向第一個孩子結點,右指標指向它在樹中的相鄰兄弟結點

。這種表示樹的方法叫孩子兄弟表示法,通過這種方法構造的二叉樹至少包括資料域,第一個孩子指標和右兄弟指標。

typedef struct CSNode {
	int data;
	struct CSNode *firstChild, *nextSibling;
}CSNode, *CSTree;

二、題目

利用遞迴演算法及孩子兄弟表示法存入下圖的樹,求出每個結點的編號,資料及所有的孩子結點。其中圓角矩形內為結點資料,旁邊數字為結點編號,編號為0的結點為根節點,箭頭指向的結點為箭尾的孩子結點。

普通樹
原樹對應的二叉樹

 

 三、程式碼

#define MAXQUEUESIZE 10

#include<iostream>
#include<malloc.h>

using namespace std;

typedef struct CSNode {
	int data;
	int number;
	struct CSNode *firstChild, *nextSibling, *parent;
}CSNode, *CSTree;

int number = 0;
int yon = 0;
int yesOrNo[] = { 1,1,0,0,1,1,1,0,1,0,0,1,0,0,0,0 };
int numData[] = { 1,2,4,3,5,7,8,6 };

CSTree treeParent = NULL;

int OperationTree(CSTree &T) {
	T = (CSTree)malloc(sizeof(CSNode));
	if (!T)
	{
		cout << "空間分配失敗(Allocate space failure.)" << endl;
		exit(OVERFLOW);
	}
	T->data = numData[number];
	T->number = number;
	number++;
	T->firstChild = NULL;
	T->nextSibling = NULL;
	T->parent = treeParent;	
	return 1;
}

int RecursionEstablishTree(CSTree &T) {
	OperationTree(T);
	treeParent = T;
	if (yesOrNo[yon++])
		RecursionEstablishTree(T->firstChild);
	treeParent = T;
	if (yesOrNo[yon++])
		RecursionEstablishTree(T->nextSibling);
	return 1;
}

void VisitCSTree(CSTree T) {
	cout << "The number of present node is :" << T->number << ",";
	cout << "and the data is :" << T->data << ".";
	if (T->firstChild) {
		cout << "This node has child and the number is :" << T->firstChild->number;
		CSTree p = T->firstChild;
		while (p->nextSibling) {
			cout << " , " << p->nextSibling->number;
			p = p->nextSibling;
		}
		
	}
	cout << endl;
}

//Visit tree use the preorder technique. 
void PreOrderVisitTree(CSTree T) {
	if (T)
	{
		VisitCSTree(T);
		PreOrderVisitTree(T->firstChild);
		PreOrderVisitTree(T->nextSibling);
	}
}

int TreeHeight(CSTree T) {
	int hc, hs;
	if (T == NULL)
		return 0;
	else
	{
		hc = TreeHeight(T->firstChild);
		hs = TreeHeight(T->nextSibling);
		if (hc + 1 > hs)
			return (hc + 1);
		else
			return hs;
	}
}

void main() {
	CSTree T;
	RecursionEstablishTree(T);
	PreOrderVisitTree(T);
	cout << "The hight of tree is :" << TreeHeight(T) << endl;
}


四、實現效果