Chapter 4 Tree

二叉樹

#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct BTNode
{
	ElemType Data;		//數據元素
	struct BTNode *Lchild;	//指向左孩子結點
	struct BTNode *Rchild;	//指向右孩子結點
}*BTree,*Position ;
void CreateBTree(BTree &T, char *str)  
{
	BTree St[MaxSize];
	Position P = NULL;
	int Top = -1, k, j = 0;
	char ch = str[j];
	T = NULL;		//建立的二叉樹初始時爲空
	while (ch != '\0')  	//str未掃描完時循環
	{
		switch (ch)
		{
		case '(':Top++; St[Top] = P; k = 1; break;		//爲左孩子結點
		case ')':Top--; break;
		case ',':k = 2; break;                      		//爲孩子結點右結點
		default:P = (BTNode*)malloc(sizeof(BTNode));
			P->Data = ch; P->Lchild = P->Rchild = NULL;
			if (T == NULL)                    	 	//P爲二叉樹的根結點
				T = P;
			else  						//已建立二叉樹根結點
			{
				switch (k)
				{
				case 1:St[Top]->Lchild = P; break;
				case 2:St[Top]->Rchild = P; break;
				}
			}
		}
		ch = str[++j];
	}
}

Position FindNode(BTree T, ElemType X) //查找某一節點
{
	Position P;
	if (T == NULL)
		return NULL;
	else if (T->Data == X)   //找到了
		return T;
	else
	{
		P = FindNode(T->Lchild, X);           //遞歸查找左子樹
		if (P != NULL)
			return P;                     //如果找到,返回節點位置
		else
			return FindNode(T->Rchild, X); //遞歸查找右子樹
	}
}

Position LchildNode(Position P) //返回左孩子
{
	return P->Lchild;
}

Position RchildNode(Position P) //返回右孩子
{
	return P->Rchild;
}

int BTreeHeight(BTree T)
{
	int LHeight, RHeight;
	if (T == NULL) 
		return 0; 				//空樹的高度爲0
	else
	{
		LHeight = BTreeHeight(T->Lchild);	//求左子樹的高度爲LHeight
		RHeight = BTreeHeight(T->Rchild);	//求右子樹的高度爲RHeight
		return (LHeight > RHeight) ? (LHeight + 1) : (RHeight + 1);
	}
}

void DispBTree(BTree T)
{
	if (T != NULL)
	{
		printf("%c", T->Data);
		if (T->Lchild != NULL || T->Rchild != NULL)
		{
			printf("(");				//有孩子結點時才輸出(
			DispBTree(T->Lchild);			//遞歸處理左子樹
			if (T->Rchild != NULL) printf(",");	//有右孩子結點時才輸出,
			DispBTree(T->Rchild);			//遞歸處理右子樹
			printf(")");				//有孩子結點時才輸出)
		}
	}
}

int NodeNum(BTree T) //計算樹的節點個數
{
	if (T)
		return NodeNum(T->Lchild) + NodeNum(T->Rchild) + 1;
	else
		return 0;
}

void PreOrder(BTree T) //前序遍歷
{
	if (T == NULL)
		return;
	printf("%c ", T->Data);
	PreOrder(LchildNode(T));
	PreOrder(RchildNode(T));
}

void InOrder(BTree T) //中序遍歷
{
	if (T == NULL)
		return;
	InOrder(LchildNode(T));
	printf("%c ", T->Data);
	InOrder(RchildNode(T));
}

void PostOrder(BTree T)  //後序遍歷
{
	if (T == NULL)
		return;
	PostOrder(LchildNode(T));
	PostOrder(RchildNode(T));
	printf("%c ", T->Data);
}

void PrintNodeAtLevel(BTree T, int Level) //打印當前層的節點
{
	// 空樹或層級不合理
	if (T == NULL || Level < 1)
		return;
	if (Level == 1)
	{
		printf("%c ", T->Data);
		return;
	}
	// 左子樹的 level - 1 級
	PrintNodeAtLevel(T->Lchild, Level - 1);
	// 右子樹的 level - 1 級
	PrintNodeAtLevel(T->Rchild, Level - 1);
}

void TravLevel(BTree T)  //逐層遍歷二叉樹
{
	if (T == NULL)
		return;
	int Height = BTreeHeight(T);
	int i;
	for (i = 1; i <= Height; i++)
	{
		PrintNodeAtLevel(T, i);
		printf("\n");
	}
}


int main()
{
	BTree T;
	T = (BTNode*)malloc(sizeof(BTNode));
	CreateBTree(T, "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
	printf("輸出二叉樹:");
	DispBTree(T);
	printf("\n");
	Position N = FindNode(T, 'H');
	Position P = LchildNode(N);
	printf("H的左孩子是:%c ,", P->Data);
	P = RchildNode(N);
	printf("右孩子是: %c .\n", P->Data);
	printf("二叉樹b的深度: %d.\n", BTreeHeight(T));
	printf("二叉樹b的結點個數: %d.\n", NodeNum(T));
	printf(" 先序遍歷序列:\n");
	printf("     遞歸算法:"); PreOrder(T); printf("\n");
	printf(" 中序遍歷序列:\n");
	printf("     遞歸算法:"); InOrder(T); printf("\n");
	printf(" 後序遍歷序列:\n");
	printf("     遞歸算法:"); PostOrder(T); printf("\n");
	printf(" 層次遍歷序列:"); printf("\n");
	TravLevel(T); printf("\n");

	return 0;
}

二叉搜索樹

#include <stdio.h>
#include <malloc.h>
typedef int KeyType;
typedef char InfoType[10];
typedef struct TreeNode           		//記錄類型
{
	KeyType Key;              		//關鍵字項
	InfoType Data;             		//其他數據域
	struct TreeNode *Lchild, *Rchild;	//左右孩子指針
} *BSTree,*Position;
int InsertBST(BSTree &T, KeyType K)
{
	if (T == NULL)				//原樹爲空, 新插入的記錄爲根結點
	{
		T = (TreeNode*)malloc(sizeof(TreeNode));
		T->Key = K;
		T->Lchild = T->Rchild = NULL;
		return 0;
	}
    if (K == T->Key) 				//樹中存在相同關鍵字的結點,返回-1
		return -1;
	else if (K < T->Key)
		return InsertBST(T->Lchild, K);	//插入到T的左子樹中
	else if(K > T->Key)
		return InsertBST(T->Rchild, K);  //插入到T的右子樹中
}

void DispBST(BSTree T)		                 //輸出一棵排序二叉樹
{
	if (T != NULL)
	{
		printf("%d", T->Key);
		if (T->Lchild != NULL || T->Rchild != NULL)
		{
			printf("(");					//有孩子結點時才輸出(
			DispBST(T->Lchild);				//遞歸處理左子樹
			if (T->Rchild != NULL)
				printf(",");	//有右孩子結點時才輸出,
			DispBST(T->Rchild);				//遞歸處理右子樹
			printf(")");					//有孩子結點時才輸出)
		}
	}
}
Position CreateBST(KeyType a[], int n)	//返回BST樹根結點
{
	BSTree T = NULL;         			//初始時T爲空樹
	int i = 0;
	while (i < n)
	{
		printf("   第%d步,插入%d元素:", i + 1, a[i]);
		InsertBST(T, a[i++]);  			//將關鍵字a[i]插入二叉排序樹T中
		DispBST(T); printf("\n");
	}
	return T;               			//返回建立的二叉排序樹的根
}
Position SearchBST(BSTree T, KeyType K)
{
	if (T == NULL)      	
		return T;
	if (K < T->Key)
		return SearchBST(T->Lchild, K);  //在左子樹中遞歸查找
	else if (K > T->Key)
		return SearchBST(T->Rchild, K);  //在右子樹中遞歸查找
	else
		return T;
}
Position SearchBST1(BSTree T, KeyType K, BSTree f1, BSTree &f)
/*在T中查找關鍵字爲k的結點,若查找成功,該函數返回該結點的指針,
  f返回其雙親結點;否則,該函數返回NULL。其調用方法如下:
  SearchBST(bt,x,NULL,f);
  這裏的第3個參數f1僅作中間參數,用於求f,初始設爲NULL*/
{
	if (T == NULL)
	{
		f = NULL;
		return NULL;
	}
	else if (K == T->Key)
	{
		f = f1;
		return T;
	}
	else if (K < T->Key)
		return SearchBST1(T->Lchild, K, T, f);  //在左子樹中遞歸查找
	else 
		return SearchBST1(T->Rchild, K, T, f);  //在右子樹中遞歸查找
}

Position FindMin(BSTree T)    //遞歸實現
{
	if (T == NULL)
		return NULL;
	if (T->Lchild == NULL)
		return T;
	else
		return FindMin(T->Lchild);
}

Position FindMax(BSTree T)   //非遞歸實現
{
	if (T != NULL)
		while (T->Rchild != NULL)
			T = T->Rchild;
	return T;
}

Position DeleteBST(BSTree T, KeyType K)
{
	Position TmpCell;
	if (T == NULL) //樹T爲空
		return T;
	if (K < T->Key)
		T->Lchild = DeleteBST(T->Lchild, K);   //遞歸查找左子樹
	else if (K > T->Key)
		T->Rchild = DeleteBST(T->Rchild, K);   //遞歸查找右子樹
	else  //找到節點
	{
		if (T->Lchild && T->Rchild)            //有兩個孩子
		{
			TmpCell = FindMin(T->Rchild);  //查找右子樹中最小的節點
			T->Key = TmpCell->Key;
			T->Rchild = DeleteBST(T->Rchild, T->Key);
		}
		else                                   //只有一個孩子或沒有孩子
		{
			TmpCell = T;
			if (T->Lchild == NULL)         //沒有左孩子
				T = T->Rchild;
			else if (T->Rchild == NULL)    //沒有右孩子
				T = T->Rchild;
			free(TmpCell);
		}
	}
	return T;
}

Position Search1(BSTree T, KeyType K) //遞歸查找某一節點
{
	if (T == NULL)
		return NULL;
	printf("%d ",T->Key);
	if (K < T->Key)
		return Search1(T->Lchild, K);
	else if (K > T->Key)
		return Search1(T->Rchild, K);
	else
		return T;
}

Position Search2(BSTree T, KeyType K) //非遞歸查找某一節點
{
	if (T == NULL)
		return NULL;
	while (T) {
		printf("%d ", T->Key);
		if (K < T->Key)
			T = T->Lchild;
		else if (K > T->Key)
			T = T->Rchild;
		else
			return T;
	}
}

int IsBST(BSTree T)    //判斷該樹是否爲二叉排序樹 
{
	                       //靜態變量,只執行一次!!!
	static int  flag = 1;  //標記節點是否符合二叉排序樹的要求
	static int LastKey = 0;//記錄上一節點的關鍵值
	                       //類似中序遍歷!!!
	if (T->Lchild && flag)
		IsBST(T->Lchild);
	if (T->Key < LastKey)
		flag = 0;
	LastKey = T->Key;
	if (T->Rchild && flag)
		IsBST(T->Rchild);
	return  flag;
}

int Compare(BSTree T, BSTree P)  //比較兩棵二叉樹是否相同
{
	if (T == NULL && P == NULL)
		return 1;
	else if (T != NULL && P != NULL)
	{
		if (T->Key == P->Key)
			return Compare(T->Lchild, P->Lchild) && Compare(T->Rchild, P->Rchild);
		else
			return 0;
	}
	else
		return 0;
}
void main()
{
	BSTree T;
	int x = 46, i;
	KeyType a[] = { 4,9,0,1,8,6,3,5,2,7 };
	int n = 10;
	printf(" 創建一棵BST樹:\n");
	T = CreateBST(a, n);
	printf("   BST:"); DispBST(T); printf("\n");
	(IsBST(T) == 1) ? printf("bt是一棵BST樹 \n") : printf("bt不是一棵BST樹\n");
	printf("查找關鍵字(遞歸):");
	Search1(T, 6);
	printf("\n");
	printf("查找關鍵字(非遞歸):");
	Search2(T, 6);
	printf("\n");
	printf("刪除操作:\n");
	printf("原BFS:");
	DispBST(T); printf("\n");
	printf("刪除節點4:");
	DeleteBST(T, 4);
	DispBST(T); printf("\n");
	printf("刪除節點5:");
	DeleteBST(T, 5);
	DispBST(T); printf("\n");
}

平衡二叉樹

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct AvlNode
{
	ElementType Element;
	struct AvlNode *Left;
	struct AvlNode *Right;
	int Height;
}*AvlTree,*Position;

int Height(Position P)
{
	if (P == NULL)
		return -1;
	else
		return P->Height;
}

int Max(int a, int b)
{
	if (a > b)
		return a;
	else
		return b;
}

Position SingleRotateWithLeft(Position K2)
{
	Position K1;

	K1 = K2->Left;
	K2->Left = K1->Right;
	K1->Right = K2;

	K1->Height = Max(Height(K1->Right), Height(K1->Left)) + 1;
	K2->Height = Max(Height(K2->Right), Height(K2->Left)) + 1;

	return K1;
}

Position SingleRotateWithRight(Position K2)
{
	Position K1;

	K1 = K2->Right;
	K2->Right = K1->Left;
	K1->Left = K2;

	K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;
	K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;

	return K1;
}

Position DoubleRotateWithLeft(Position K3)
{
	K3->Left = SingleRotateWithRight(K3->Left);

	return SingleRotateWithLeft(K3);
}

Position DoubleRotateWithRight(Position K3)
{
	K3->Right = SingleRotateWithLeft(K3->Right);

	return SingleRotateWithRight(K3);
}

AvlTree Insert(AvlTree T, ElementType X)
{
	if (T == NULL)
	{
		T = (AvlNode*)malloc(sizeof(AvlNode));
		T->Element = X;
		T->Height = 0;
		T->Left = T->Right = NULL;
	}
	else
	{
		if (X < T->Element)
		{
			T->Left = Insert(T->Left, X);
			if (Height(T->Left) - Height(T->Right) == 2)
			{
				if (X < T->Left->Element)
					T = SingleRotateWithLeft(T);
				else
					T = DoubleRotateWithLeft(T);
			}
		}
		else if (X > T->Element)
		{
			T->Right = Insert(T->Right, X);
			if (Height(T->Right) - Height(T->Left) == 2)
			{
				if (X > T->Right->Element)
					T = SingleRotateWithRight(T);
				else
					T = DoubleRotateWithRight(T);
			}
		}
	}
	T->Height = Max(Height(T->Left), Height(T->Right)) + 1;

	return T;
}

Position FindMin(AvlTree T)  
{
	if (T == NULL)
		return NULL;
	if (T->Left == NULL)
		return T;
	else
		return FindMin(T->Right);
}

Position Delete(AvlTree T,ElementType X)
{
	Position Temp;
	if (T == NULL)
		return NULL;
	else if (X < T->Element)
	{
		T->Left = Delete(T->Left, X);
		if (Height(T->Right) - Height(T->Left) == 2)
			//由於在左子樹的刪除導致在T處平衡被破壞  
			if (Height(T->Right->Left) > Height(T->Right->Right))
				//如果T->Right的左子樹比右子樹高,執行雙旋轉  
				T = DoubleRotateWithRight(T);
			else
				//否則執行單旋轉  
				T = SingleRotateWithRight(T);
	}
	else if (X > T->Element)
	{
		T->Right = Delete(T->Right, X);
		if (Height(T->Left) - Height(T->Right) == 2)
			//由於在右子樹的刪除導致在T處平衡被破壞  
			if (Height(T->Left->Right) > Height(T->Left->Left))
				//如果T->Left的左子樹比右子樹要高,執行單旋轉  
				T = SingleRotateWithLeft(T);
			else
				//否則執行雙旋轉  
				T = DoubleRotateWithLeft(T);
	}
	else 
	{//正常的刪除策略  
		if (T->Left && T->Right)
		{
			Temp = FindMin(T->Right);
			T->Element = Temp->Element;
			T->Right = Delete(T->Right, T->Element);
		}
		else
		{
			Temp = T;
			if (T->Left == NULL)
				T = T->Right;
			else if (T->Right == NULL)
				T = T->Left;
			free(Temp);
		}
	}	
	if (T)
		//最後更新高度,此處可能T已經被設置成了NULL,所以需要檢測下  
	    T->Height = Max(Height(T->Left), Height(T->Right)) + 1;

	return T;
}

int main()
{
	AvlTree T = (AvlNode*)malloc(sizeof(AvlNode));
	T = NULL;
	int A[] = { 0,1,2,3,4,5,6,7,8,9 };
	for (int i = 0; i < 10; i++)
		T = Insert(T, A[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章