1. 程式人生 > >C語言:線索二叉樹的線索化及其遍歷實現

C語言:線索二叉樹的線索化及其遍歷實現

       前序和中序遍歷都實現了,後序線索化還不是很明白!如有大神看到,望指正!不勝感激!

// 中序線索二叉樹實現.cpp : 定義控制檯應用程式的入口點。
//
#include "stdafx.h"
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
#define ElementType char
typedef enum{ Link, Thread } PointerTag;
//線索儲存標誌位
//Link(0):表示指向左右孩子的指標
//Thread(1):表示指向前驅和後繼的線索
typedef struct BiThrNode
{
	ElementType Data;
	struct BiThrNode *Left;
	struct BiThrNode *Right;
	PointerTag Ltag;
	PointerTag Rtag;
}BiThrNode, *BiThrTree;
//全域性變數,始終指向剛剛問過的節點
BiThrNode *pre;
//建立一個二叉樹:利用前序遍歷建立二叉樹
//函式宣告
void CreatTree(BiThrTree *BT);
void DestroyBiTree(BiThrTree &T);
void DestroyBiThrTree(BiThrTree &Thrt);
//中序線索化二叉樹,並且實現中序遍歷操作函式定義
void InThreding(BiThrTree BT);
void InorderThreding(BiThrTree *p, BiThrTree T);
void InOrderTraverse(BiThrTree T);
void InOrderTraverse_Iter(BiThrTree T);

//前序線索化二叉樹,並且實現前序遍歷操作函式定義
void PreThreding(BiThrTree BT);
void PreorderThreding(BiThrTree *p, BiThrTree T);
void PreOrderTraverse(BiThrTree T);
void PreOrderTraverse_Iter(BiThrTree T);

//後序線索化二叉樹,並且實現後序遍歷操作函式定義
void PostThreding(BiThrTree BT);
void PostorderThreding(BiThrTree *p, BiThrTree T);
void PostOrderTraverse(BiThrTree T);
void PostOrderTraverse_Iter(BiThrTree T);

//函式定義
void CreatTree(BiThrTree *BT)
{
	char ch;
	cin >> ch;
	if (ch == '#') *BT = NULL;
	else
	{
		*BT = (BiThrNode*)malloc(sizeof(struct BiThrNode));
		(*BT)->Data = ch;
		(*BT)->Ltag = Link;
		(*BT)->Rtag = Link;
		CreatTree(&(*BT)->Left);
		CreatTree(&(*BT)->Right);
	}
}
void PostOrderTraverse(BiThrTree T)
{
	if (T)
	{
		PostOrderTraverse(T->Left);
		PostOrderTraverse(T->Right);
		cout << T->Data;
	}
}
void  InOrderTraverse(BiThrTree T)
{
	if (T)
	{
		InOrderTraverse(T->Left);
		cout << T->Data;
		InOrderTraverse(T->Right);
	}
}
void  PreOrderTraverse(BiThrTree T)
{
	if (T)
	{
		cout << T->Data;
		PreOrderTraverse(T->Left);
		PreOrderTraverse(T->Right);

	}
}
void DestroyBiTree(BiThrTree &T)
{
	if (T)  // 非空樹  
	{
		if (T->Ltag == Link)                // 有左孩子  
			DestroyBiTree(T->Left);         // 銷燬左孩子子樹  
		if (T->Rtag == Link)                // 有右孩子  
			DestroyBiTree(T->Right);        // 銷燬右孩子子樹  
		free(T);    // 釋放根結點  
		T = NULL;   // 空指標賦0  
	}
}
// 初始條件:線索二叉樹Thrt存在。操作結果:銷燬線索二叉樹Thrt  
void DestroyBiThrTree(BiThrTree &T)
{
	if (T)             // 頭結點存在  
	{
		if (T->Left)    // 根結點存在  
		{
			DestroyBiTree(T->Left); // 遞迴銷燬頭結點lchild所指二叉樹  
		}
		free(T);     // 釋放頭結點  
		T = NULL;    // 線索二叉樹Thrt指標賦0  
	}
}
//前序線索化二叉樹,並且實現前序遍歷操作函式定義
void PreThreding(BiThrTree BT)
{
	if (BT)
	{
		if (!BT->Left)
		{
			BT->Ltag = Thread;
			BT->Left = pre;
		}
		if (!pre->Right)
		{
			pre->Right = BT;
			pre->Rtag = Thread;
		}
		pre = BT;
		if (BT->Ltag == Link)
			PreThreding(BT->Left);//遞迴左孩子線索化
		if (BT->Rtag == Link)
			PreThreding(BT->Right);//遞迴右孩子線索化
	}
}
void PreorderThreding(BiThrTree *p, BiThrTree T)
{//p結點為頭結點,T結點為樹根結點
	*p = (BiThrNode*)malloc(sizeof(struct BiThrNode));
	(*p)->Ltag = Link;
	(*p)->Rtag = Thread;
	(*p)->Right = *p;
	if (!T)  (*p)->Left = *p;
	else
	{
		(*p)->Left = T;
		pre = *p;
		PreThreding(T);
		pre->Right = *p;
		pre->Rtag = Thread;
		(*p)->Right = pre;
	}
}
void PreOrderTraverse_Iter(BiThrTree T)
{
	BiThrTree p = T->Left;
	while (p != T)
	{
		cout << p->Data;
		if (p->Ltag == Link)
			p = p->Left;
		else
			p = p->Right;
	}
}
//與前序有關的函式實現結束

//中序線索化二叉樹,並且實現中序遍歷操作
//中序遍歷線索化的過程
void InThreding(BiThrTree BT)
{
	if (BT)
	{
		InThreding(BT->Left);//遞迴左孩子線索化
		//結點處理
		if (!BT->Left)      //如果該結點沒有左孩子,
		{
			BT->Ltag = Thread;
			BT->Left = pre;
		}
		if (!pre->Right)
		{
			pre->Rtag = Thread;
			pre->Right = BT;
		}
		pre = BT;
		InThreding(BT->Right);//遞迴右孩子線索化
	}
}
void InorderThreding(BiThrTree *p, BiThrTree T)
{//p結點為頭結點,T結點為樹根結點
	*p = (BiThrNode*)malloc(sizeof(struct BiThrNode));//建立一個頭結點
	(*p)->Ltag = Link;
	(*p)->Rtag = Thread;
	(*p)->Right = *p;          //有指標回指
	if (!T)  (*p)->Left = *p;   //若二叉樹為空,則做指標回指
	else
	{
		(*p)->Left = T;        //若二叉樹不為空,Left指向根結點
		pre = *p;
		InThreding(T);       //中序遍歷進行中序線索化
		//最後一個結點線索化
		pre->Rtag = Thread;
		pre->Right = *p;    //終端結點指向頭結點
		(*p)->Right = pre;  //頭結點的右指標指向終端結點
	}

}
//中序遍歷二叉樹,非遞迴實現
void InOrderTraverse_Iter(BiThrTree T)
{
	BiThrTree p;
	p = T->Left;      //p指向根結點T
	while (p != T)     //二叉樹非空或遍歷未結束
	{
		while (p->Ltag == Link)  //訪問左子樹為空的結點
		{
			p = p->Left;
		}
		cout << p->Data;
		while ((p->Rtag == Thread)&&(p->Right != T))  //p的Right指向後繼,訪問p結點的後繼
		{
			p = p->Right;
			cout << p->Data;
		}
		p = p->Right;   //p的Right指向右孩子
	}
}
//與中序有關的函式實現結束

//後序線索化二叉樹,並且實現後序遍歷操作函式定義
void PostThreding(BiThrTree BT)
{
	if (BT)
	{
		PostThreding(BT->Left);
		PostThreding(BT->Right);
		if (!BT->Left)
		{
			BT->Ltag = Thread;
			BT->Left = pre;
		}
		if (!pre->Right)
		{
			pre->Rtag = Thread;
			pre->Right = BT;
		}
		pre = BT;
	}
}
void PostorderThreding(BiThrTree *p, BiThrTree T)
{
	//p結點為頭結點,T結點為樹根結點
	*p = (BiThrNode*)malloc(sizeof(struct BiThrNode));
	(*p)->Ltag = Link;
	(*p)->Rtag = Thread;

	if (!T)  (*p)->Left = (*p)->Right = *p;
	else
	{
		(*p)->Left = (*p)->Right = *p;
		pre = *p;
		PostThreding(T);
		if (pre->Rtag != Link)  // 最後一個結點沒有右孩子  
		{
			pre->Right = *p;  // 最後一個結點的後繼指向頭結點  
			pre->Rtag = Thread;
		}
	}
}
void PostOrderTraverse_Iter(BiThrTree T)
{
	BiThrTree p =T->Left;
	while (p->Ltag == Link || p->Rtag == Link)   //有左孩子先訪問左孩子,沒有左孩子先訪問右孩子  
	{
		while (p->Ltag == Link)
			p = p->Left;
		if (p->Rtag == Link)                //訪問左孩子為空的結點的右孩子  
			p = p->Right;
	}
	cout << p->Data;
	while (p != T)                        //p不為根結點  
	{
		if (p->Rtag == Link)              //若p是有兄弟的左孩子  
		{
			if (pre->Rtag == Thread || p == pre->Right) //若p是雙親的右孩子或是獨生左孩子,則後繼為雙親  
				p = pre;
			else
			{
				p = pre->Right;              //後繼為雙親的右子樹上按照後序遍歷訪問的第一個結點。  
				while (p->Ltag == Link || p->Rtag == Link)
				{
					if(p->Ltag == Link)
						p = p->Left;
					if (p->Rtag == Link)
						p = p->Right;
				}
			}
		}
		else
			p = p->Right;             //p指向後繼  
		cout << p->Data;
	}
}
//與後序有關的函式實現結束
int _tmain(int argc, _TCHAR* argv[])
{
	BiThrTree T = NULL;
	BiThrTree BT = NULL;
	BiThrTree A = NULL;
	BiThrTree BA = NULL;
	BiThrTree D = NULL;
	BiThrTree BD = NULL;
	cout << "按照前序遍歷建立二叉樹:" << endl;
	CreatTree(&T);
	cout << "中序遍歷:";
	InOrderTraverse(T);
	cout << endl;
	cout << "中序線索化!" << endl;
	InorderThreding(&BT, T);
	cout << "中序線索化後輸出:";
	InOrderTraverse_Iter(BT);
	cout << endl;
	DestroyBiThrTree(BT);

	cout << "按照前序遍歷建立二叉樹:" << endl;
	CreatTree(&A);
	cout << "前序遍歷:";
	PreOrderTraverse(A);
	cout << endl;
	cout << "前序線索化!" << endl;
	PreorderThreding(&BA, A);
	cout << "前序線索化後輸出:";
	PreOrderTraverse_Iter(BA);
	cout << endl;
	DestroyBiThrTree(BA);

	cout << "按照前序遍歷建立二叉樹:" << endl;
	CreatTree(&D);
	cout << "後序遍歷:";
	PostOrderTraverse(D);
	cout << endl;
	cout << "後序線索化!" << endl;
	PostorderThreding(&BD, D);
	cout << "後序線索化後輸出:";
	PostOrderTraverse_Iter(BD);
	DestroyBiThrTree(BD);
	cout << endl;
	return 0;
}