線索二叉樹的實現

<span style="font-size:18px;">/*
 1.二叉樹遍歷算法提供了二叉樹的一次性遍歷,但是二叉樹遍歷算法沒法實現用戶程序像分步
 遍歷單鏈表那樣分步遍歷二叉樹。線索二叉樹就是專門爲實現分步遍歷二叉樹而設計的。線索二叉樹可以實現像雙向
 鏈表那樣,既可以從前向後分步遍歷二叉樹,又可以從後向前分步遍歷二叉樹
 2.當按某種規則遍歷二叉樹時,保存遍歷時獲得的節點的後繼節點信息和前驅節點信息的最常用的方法是創建線索二叉樹
 3.線索二叉樹的規定:當某節點的左指針爲空時,令該節點指針指向按某種方法遍歷二叉樹時獲得的該節點的前驅節點;當某節點的右指針
 爲空時,令該指針指向按某種方法遍歷二叉樹時獲得該節點的後繼節點
 4.咱們把節點中指向前驅和後繼節點的指針稱爲線索,把在二叉樹的節點上加上線索的二叉樹稱爲線索二叉樹,把對二叉樹以某種方法(
 如前序,中序,或後序方法)遍歷使其變爲線索二叉樹的過程稱按該方法對二叉樹進行線索化。
 5.線索二叉樹的用途:一旦創建了某種方式的線索二叉樹,用戶程序就可以像操做雙向鏈表同樣操做該線索二叉樹。
 好比,一旦創建了中序線索二叉樹,用戶程序就可以設計一個正向循環結構遍歷該二叉樹的所有節點,循環初始定位在中序線索二叉樹的第一個位置
 ,每次循環使指針指向當前節點的中序遍歷的後繼節點,當指針指向中序線索二叉樹的最後一個節點位置後時,循環過程結束;
 或者用戶程序可以設計一個反向循環結構遍歷該二叉樹的所有結點,循環初始定位在中序線索二叉樹的最後一個節點位置,每次循環使指針向當前
 節點的中序遍歷的前驅節點位置,當指針指向中序線索二叉樹的第一個節點位置前時,循環結束。
  
	  
*/
#include<stdio.h>
#include<malloc.h>
typedef char DataType;
//中序線索二叉樹中節點的結構體
typedef struct Node{

	DataType data;//數據域
	int leftThread;//左線索
	struct Node *leftChild;//左指針
	struct Node *rightChild;//右指針
	int rightThread;//右線索
}ThreadBiNode;//節點的結構體定義

typedef struct{

	ThreadBiNode *root;//頭指針
	ThreadBiNode *current;//當前節點指針
	int nextComplete;//遍歷結束標誌
}ThreadBiTree;




//進行中序線索化的函數
void InThread(ThreadBiNode *current,ThreadBiNode **pre){
	//中序線索二叉樹
	//current爲當前節點指針,pre爲當前節點的中序前驅節點指針
	if(current!=NULL){
	
		InThread(current->leftChild,pre);//中序線索化左子樹
		if(current->leftChild==NULL){
		
			current->leftThread=1;//創建線索標誌
			current->leftChild=*pre;//創建左線索指針
		}else{
			current->leftThread=0;//有左節點
		}

		if(current->rightChild!=NULL){
		
			current->rightThread=0;//有右子樹
		}else{
		
			current->rightThread=1;
		}


		if((*pre)->rightChild==NULL){
		
			(*pre)->rightThread=1;//創建右線索標誌
			(*pre)->rightChild=current;//創建右線索指針
		}else{
		
			current->rightThread=0;//存在右子樹
		}
		*pre=current;//前序節點指針等於當前節點指針
		InThread(current->rightChild,pre);//中序化右子樹

	}
}

void CreatInThread(ThreadBiNode **root){

	//建立中序線索化二叉樹tree
	ThreadBiNode *t=*root;//保存原二叉樹根節點指針
	ThreadBiNode *current,*pre=*root;
	//創建頭節點
	*root=(ThreadBiNode *)malloc(sizeof(ThreadBiNode));
	if(t==NULL){
	
		(*root)->leftThread=0;
        (*root)->rightThread=1;
		(*root)->leftChild=*root;
		(*root)->rightChild=*root;
		printf("the root is null\n");
	}else{
	//當二叉樹爲非空
	
		current=t;
		(*root)->leftChild=t;//置頭節點的左指針
		(*root)->leftThread=0;//置頭節點的左線索

		


		InThread(current,&pre);//線索化二叉樹

		pre->rightChild=*root;//置最後一個節點的右指針
		pre->rightThread=1;//置最後一個節點的右線索
		(*root)->rightChild=pre;//置當前的右指針
		(*root)->rightThread=1;//置頭節點的右線索
	}

}


void ThreadInitiate(ThreadBiTree *tree,ThreadBiNode *root){
//初始化中序線索二叉樹函數
	tree->root=root;
	tree->current=root;
	if(root=NULL){
	
		tree->nextComplete=1;
	}else{
	
		tree->nextComplete=0;
	}
}


void First(ThreadBiTree *tree){
//使中序線索二叉樹tree的當前節點指針指向中序遍歷的第一個節點
	tree->current=tree->root;
	while(tree->current->leftThread==0){
	
		tree->current=tree->current->leftChild;
	}

	if(tree->current==tree->root){
	
		tree->nextComplete=1;
	}else{
	
		tree->nextComplete=0;
	}
    
}



void Next(ThreadBiTree *tree){
//使中序線索二叉樹tree的當前節點指針指向中序遍歷的下一個節點

	ThreadBiNode *p=tree->current->rightChild;
    
	if(tree->nextComplete==1){
	
		return ;
	}

	if(tree->current->rightThread==0){
	
		while(p->leftThread==0){
		
			p=p->leftChild;
			
		}
	}
    

	tree->current=p;
	if(tree->current==tree->root){
		tree->nextComplete=1;
	}


}


int EndOfNext(ThreadBiTree *tree){
//推斷是否已到中序線索二叉樹tree的尾部
//nextComplete=1表示已到,不然未到
	return tree->nextComplete;
}



ThreadBiNode *GetTreeNode(DataType item,ThreadBiNode *left,
						  ThreadBiNode *right){
	//建立二叉樹節點函數
	ThreadBiNode *p;
	p=(ThreadBiNode *)malloc(sizeof(ThreadBiNode));
	p->data=item;
	p->leftChild=left;
	p->rightChild=right;
	return p;
}



void MakeCharTree(ThreadBiNode **root){
//建立二叉樹函數
	ThreadBiNode *b,*c,*d,*e,*f,*g;
	g=GetTreeNode('G',NULL,NULL);
	d=GetTreeNode('D',NULL,g);
	b=GetTreeNode('B',d,NULL);
	e=GetTreeNode('E',NULL,NULL);
	f=GetTreeNode('F',NULL,NULL);
	c=GetTreeNode('C',e,f);
	*root=GetTreeNode('A',b,c);
}



void main(){

	ThreadBiNode *root;
	ThreadBiTree tree;

	MakeCharTree(&root);//構造二叉樹
	
	CreatInThread(&root);//建立中序線索二叉樹
	printf("二叉樹中序正向遍歷序列爲:");
	ThreadInitiate(&tree,root);//循環初始化
	for(First(&tree);!EndOfNext(&tree);Next(&tree)){//循環遍歷訪問

		printf("%c  ",tree.current->data);
}

	printf("\n");


}</span>


執行結果:算法

相關文章
相關標籤/搜索