輸出二叉樹前序序列中的第K個結點內容&測試

假設已經建立好二叉樹,知道二叉樹的前序序列,要輸出前序序列中第k(1<=k<=n)個結點中的數據應該怎麼操作?

此次測試用的是三層滿二叉樹,層次遍歷序列爲ABCDEFG

總體思路就是遞歸的去前序遍歷二叉樹,設置一個全局變量i,每過一個結點就+1當作計數器,等i==k時返回那個結點的值,思路很簡單但在遞歸這個問題上懵了。

建立二叉樹沿用之前【已知前序中序創建二叉樹】的代碼簡歷,經過幾次試錯……終於寫出了一個函數。

先貼上主函數:

void main(){
	BiTree T;
	char ch;
	char A[7]={'A','B','D','E','C','F','G'};
	char B[7]={'D','B','E','A','F','C','G'};
	T=PreInCreat(A,B,0,6,0,6);//到此處均爲創建二叉樹
	//ch=FINDK(T,4);
	//cout<<"第N個結點數據是:"<<ch<<endl;//以K爲4
	FindK(T,4);
	system("pause");
}
(被//的兩條語句是用來配合課本方法輸出用的)

①課本上的FINDK():

解釋在代碼註釋中

char FINDK(BiTree P,int k){
	char ch;
	if(P==NULL)
		return '#';
	i++;
	if(i==k)
		return P->data;//以上即爲前序遍歷中visit()部分,下面是造前序部分
	ch=FINDK(P->lchild,4);
	if(ch!='#')//當ch不再是#說明找到想要的數據了,在哪找到的無從得知,但現在已經傳到本層的ch這,而且要繼續傳上去,現在是傳遞鏈的一環
		return ch;
	ch=FINDK(P->rchild,4);//所找結點的父親結點接受數據時要用到這條語句,如本題中的B結點
	return ch;//這條只是保證函數無論如何有返回,上一條return是判別語句
}

②自己寫的FindK():

void FindK(BiTree P,int k){
	if(P!=NULL){
		i++;
		if(i==6)
			cout<<P->data;//
		FindK(P->lchild,k);
		FindK(P->rchild,k);
	}
}

我把函數設置成了一個不返回值的形式,在序號對上的時候直接打印出來,但事後想萬一要求不是打印而是要取到結點值,就要改一下,應該可以設置一個全局變量,在找到的時候把值給全局變量,就不用返回。

缺點是函數無論如何都會把二叉樹所有結點遍歷一邊纔會結束

對比一下之前錯誤的想法:(memo是計數器)


首先你寫了返回值char你就必須保證該函數有一個返回值,因此被迫寫了return '#',然後會發現這個return是沒有意義的,相當於每一層調用都返回了一個#,而data夾在衆多#中,書上的代碼返回#它是有ch承接而且要做判斷的。

發現了一些問題寫在代碼最後

完整代碼:

#include<iostream>
#include<stdlib.h>
using namespace std;
int i=0;
typedef struct BiNode{
	char data;
	struct BiNode *lchild,*rchild;
}BiNode,*BiTree;

BiTree PreInCreat(char A[],char B[],int l1,int h1,int l2,int h2){//創建二叉樹
	int i,llen,rlen;
	BiTree root;
	root=(BiNode*)malloc(sizeof(BiNode));
	root->data=A[l1];
	for(i=l2;B[i]!=root->data;i++);
	llen=i-l2;
	rlen=h2-i;
	if(llen)
		root->lchild=PreInCreat(A,B,l1+1,l1+llen,l2,l2+llen-1);
	else
		root->lchild=NULL;
	if(rlen)
		root->rchild=PreInCreat(A,B,h1-rlen+1,h1,h2-rlen+1,h2);
	else
		root->rchild=NULL;
	return root;
}

void FindK(BiTree P,int k){
	if(P!=NULL){
		i++;
		if(i==6)
			cout<<P->data;//以上即爲前序遍歷中visit()部分,下面是造前序部分
		FindK(P->lchild,k);
		FindK(P->rchild,k);
	}
}

char FINDK(BiTree P,int k){
	char ch;
	if(P==NULL)
		return '#';
	i++;
	if(i==k)
		return P->data;
	ch=FINDK(P->lchild,4);//以上即爲前序遍歷中visit()部分,下面是造前序部分
	if(ch!='#')//當ch不再是#說明找到想要的數據了,在哪找到的無從得知,但現在在本層的ch這,要把他傳上去,現在是傳遞鏈的一環
		return ch;
	ch=FINDK(P->rchild,4);//所找結點的父親結點接受數據時要用到這條語句,如本題中的B結點
	return ch;//這條只是保證函數無論如何有返回,上一條return是判別??
}

void main(){
	BiTree T;
	char ch;
	char A[7]={'A','B','D','E','C','F','G'};
	char B[7]={'D','B','E','A','F','C','G'};
	T=PreInCreat(A,B,0,6,0,6);//到此處均爲創建二叉樹
	//ch=FINDK(T,4);
	//cout<<"第四個結點數據是:"<<ch<<endl;//以K爲4
	FindK(T,4);
	system("pause");
}



//發現問題:1.C++裏函數並不一定要有一個返回值,但你要記得你在定義函數的時候寫的是什麼,如果不返回了就記得寫成void
//         2.注意全局變量是要在#之後定義而不是在主函數中定義
//		   3.函數只能返回一次值,你在中間某個部分執行了return,該層函數下面的部分就都不再執行了。看FINDK()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章