1. 程式人生 > >二叉排序樹的建立(結點的插入,刪除等操作)

二叉排序樹的建立(結點的插入,刪除等操作)

二叉排序樹的理論看課本

程式碼如下:

BSTree.h

struct BSTreeNode;
typedef  struct BSTreeNode *ptrtreenode;

void MakeEmpty(ptrtreenode T);
ptrtreenode InsertBSTree(int x,ptrtreenode T); //二叉樹的插入操作
ptrtreenode FindMin(ptrtreenode T);//查詢以T為頭結點的子樹中最小的關鍵字的結點,並返回--------------------遞迴方式實現
ptrtreenode FindMin1(ptrtreenode T);//查詢以T為頭結點的子樹中最小的關鍵字的結點,並返回--------------------非遞迴方式實現
ptrtreenode DeleteBSTree(int x,ptrtreenode T);  //刪除關鍵字為x的結點(遞迴策略)
void PrintBSTree_Pre(ptrtreenode T);//先序遍歷
void PrintBSTree_Post(ptrtreenode T);//後序遍歷
void PrintBSTree_In(ptrtreenode T);//中序遍歷

BSTree.c
//name :jae chia
//purpose:建立二叉查詢樹,並進行二叉查詢樹的結點的刪除,搜尋帶有某個關鍵字的結點等
#include<stdio.h>
#include<stdlib.h>
#include"BSTree.h"
struct BSTreeNode
{
	int element;
	ptrtreenode left;
	ptrtreenode right;
	
};
/*ptrtreenode CreateBSTree() //利用這個函式建立的是帶有啞元結點的二叉查詢樹,並不合適
{
	ptrtreenode T=(ptrtreenode)malloc(sizeof(struct BSTree));
	T->left=NULL;
	T->right=NULL;
	return T;
}*/

void MakeEmpty(ptrtreenode T)
{
	if(T)
	{
		MakeEmpty(T->left);
		MakeEmpty(T->right);
		free(T);
	}
}
ptrtreenode InsertBSTree(int x,ptrtreenode T) //二叉樹的插入操作
{
	//ptrtreenode newtreenode=(ptrtreenode)malloc(sizeof(struct BSTreeNode));
	//newtreenode->element=x;
	if(NULL==T)
	{
		//ptrtreenode T=(ptrtreenode)malloc(sizeof(struct BSTreeNode));
	    T = (ptrtreenode)malloc(sizeof(struct BSTreeNode));//這裡誤寫為ptrtreenode T=(ptrtreenode)malloc(sizeof(struct BSTreeNode));相當於在if語句塊內用定義了一個T,語句塊結束,該區域性變數就銷燬
		                                                   //因此在建立一個二叉樹的根節點時,該函式返回的T仍是NULL
		if(T==NULL)
		{
			printf("Insufficient memory!\n");
			exit(0);
		}
		T->element=x;
	    T->left=NULL;
	    T->right=NULL;
	}
	else
	{   
		if(x < T->element)
		    T->left=InsertBSTree(x,T->left);
		else if(x > T->element)
			T->right=InsertBSTree(x,T->right);

	}
	return T;
}


ptrtreenode FindMin(ptrtreenode T)//查詢以T為頭結點的子樹中最小的關鍵字的結點,並返回--------------------遞迴方式實現
{
	if(T->left==NULL)
	{
		return T;
		//return FindMin(T->left);

	}
	else
	{
		return FindMin(T->left);
	}
	
}

ptrtreenode FindMin1(ptrtreenode T)//查詢以T為頭結點的子樹中最小的關鍵字的結點,並返回--------------------非遞迴方式實現
{
	while(T->left)
	{
		T=T->left;
	}
	return T;
}


ptrtreenode DeleteBSTree(int x,ptrtreenode T)  //這裡也是採用的遞迴策略
{
	ptrtreenode tmpcell;
	if(T==NULL)
	{
		printf(" element can't find\n");
		exit(0);
	}
	else if(x < T->element)  //在左分支上查詢關鍵字x,如此遞迴
	{
		T->left=DeleteBSTree(x,T->left);
	}
	else if(x > T->element)  //在右分支上查詢關鍵字x,如此遞迴
	{
		T->right=DeleteBSTree(x,T->right);

	}
	else   //找到該關鍵字
	{
		if (T->left && T->right)//所刪除關鍵字的結點的左右子樹都存在的情況下
		{
			tmpcell=FindMin(T->right);
			T->element=tmpcell->element;//找到所要刪結點的右子樹上關鍵字最小的結點,並將其關鍵字值賦給所要刪除的那個結點
			T->right=DeleteBSTree(T->element,T->right);//這時候刪除上面右子樹上關鍵字最小的那個結點(因為這時候所刪的這個結點肯定沒有左孩子,否
			                                           //則就不會是最小,因此這就相當於對僅有一個孩子的結點進行刪除操作)
		}
		else   //所刪除的關鍵字的結點的左右子樹僅存在一個
		{
			tmpcell=T;
			if(T->left==NULL)
			{
				T=T->right;
			}
			else if(T->right==NULL)
			{
				T=T->left;
			}
			free(tmpcell);

		}

	}
   return T;
}

//先序遞迴遍歷
void PrintBSTree_Pre(ptrtreenode T)
{   
	if(T)
	{ 
		printf("%d ",T->element);
		PrintBSTree_Pre(T->left);
		PrintBSTree_Pre(T->right);
	}
}
//後序遞迴遍歷
void PrintBSTree_Post(ptrtreenode T)
{
	if(T)
	{
		PrintBSTree_Post(T->left);
		PrintBSTree_Post(T->right);
		printf("%d ",T->element);
	}
}
//中序遞迴遍歷
void PrintBSTree_In(ptrtreenode T)
{
	if(T)
	{;
		PrintBSTree_In(T->left);
		printf("%d ",T->element);
		PrintBSTree_In(T->right);
	}
}


int main(void)
{
    ptrtreenode T=NULL;
	T=InsertBSTree(6,T);
	T=InsertBSTree(2,T);
	T=InsertBSTree(1,T);
	T=InsertBSTree(4,T);
	T=InsertBSTree(8,T);
	T=InsertBSTree(3,T);
	printf("先序遍歷:");
	PrintBSTree_Pre(T);
	printf("\n");
	printf("後序遍歷:");
	PrintBSTree_Post(T);
	printf("\n");
	printf("中序遍歷:");
	PrintBSTree_In(T);
	printf("\n");
	printf("刪除關鍵字為4的結點後的遍歷狀態:\n");//刪除僅有左子樹或僅有右子樹的結點(關鍵字為4)
	T=DeleteBSTree(4,T);
	printf("先序遍歷");
	PrintBSTree_Pre(T);
	printf("\n");
	printf("後序遍歷:");
	PrintBSTree_Post(T);
	printf("\n");
	printf("中序遍歷:");
	PrintBSTree_In(T);
	printf("\n");
	printf("刪除關鍵字為2的結點後的遍歷狀態:\n");//刪除左子樹和右子樹都非空的結點(關鍵字為2)
	T=DeleteBSTree(2,T);
	printf("先序遍歷");
	PrintBSTree_Pre(T);
	printf("\n");
	printf("後序遍歷:");
	PrintBSTree_Post(T);
	printf("\n");
	printf("中序遍歷:");
	PrintBSTree_In(T);
	printf("\n");

	//PrintBSTreeZ(T);
	//PrintBSTreeH(T);
	return 0;
}



執行結果: