现在的位置: 首页 > 综合 > 正文

二叉排序树

2013年09月20日 ⁄ 综合 ⁄ 共 3296字 ⁄ 字号 评论关闭
/*
功能,数据结构C语言版V2cn,P227,二叉排序树
可以进一步学习《算法导论V2cn》第12章 二叉查找树。
日期,2012年10月30日
博客,http://blog.csdn.net/shunqiziranhao007/article/details/7816771
环境,win7-32-vs2010
*/
#include <stdio.h>
#include <malloc.h>

// 数据元素个数
#define N 10

typedef int KeyType;

typedef struct
{
	KeyType key;
	int others;
} ElemType;

// 树的元素类型
typedef ElemType TElemType;

// 二叉树的二叉链表存储表示
typedef struct BiTNode
{
	TElemType data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

// 构造一个空的动态查找表DT
int InitDSTable(BiTree *DT)
{
	*DT = NULL;

	return 1;
}

// 销毁动态查找表DT
void DestroyDSTable(BiTree *DT)
{
	if(*DT)
	{
		if((*DT)->lchild)
			// 递归销毁
			DestroyDSTable(&(*DT)->lchild);
		if((*DT)->rchild)
			DestroyDSTable(&(*DT)->rchild);
		free(*DT);
		*DT = NULL;
	}
}

// 算法9.5(a) P228
// 在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素,
// 若查找成功,则返回指向该数据元素结点的指针,否则返回空指针。
BiTree SearchBST(BiTree T, KeyType key)
{
	if ( (!T) || (key == T->data.key) )
	{
		return T;
	}
	else if ( key < T->data.key )
	{
		// 在左子树中继续查找
		return SearchBST(T->lchild,key);
	}
	else
	{
		return SearchBST(T->rchild,key);
	}
}

// 算法9.5(b) P228
// 在根指针T所指二叉排序树中递归地查找其关键字等于key的数据元素,若查找
// 成功,则指针p指向该数据元素结点,并返回1,否则指针p指向查找路径上
// 访问的最后一个结点并返回0,指针f指向T的双亲,其初始调用值为NULL
void SearchBST1(BiTree *T, KeyType key, BiTree f, BiTree *p, int *flag)
{	
	if(!*T) // 查找不成功
	{
		*p = f;
		*flag = 0;
	}
	else if(key == (*T)->data.key) //  查找成功
	{
		*p = *T;	//指针p指向该数据元素结点
		*flag = 1;
	}
	else if(key < (*T)->data.key)
		SearchBST1(&(*T)->lchild,key,*T,p,flag); // 在左子树中继续查找
	else
		SearchBST1(&(*T)->rchild,key,*T,p,flag); // 在右子树中继续查找
}

// 算法9.6 P228
// 当二叉排序树T中不存在关键字等于e.key的数据元素时,插入e并返回1,否则返回0。
int InsertBST(BiTree *T, ElemType e)
{
	BiTree p,s;
	int flag;
	
	SearchBST1(T, e.key, NULL, &p, &flag);
	if(!flag) // 查找不成功
	{
		s = (BiTree)malloc(sizeof(BiTNode));
		s->data = e;
		s->lchild = s->rchild = NULL;
		if( !p )
		{
			// 被插结点*s为新的根结点
			*T = s;
		}
		else if(e.key < p->data.key)
		{
			// 被插结点*s为左孩子,值小的在左边
			p->lchild = s;
		}
		else
		{
			// 被插结点*s为右孩子,值大的在右边
			p->rchild = s;
		}
		return 1;
	}
	else
	{
		// 树中已有关键字相同的结点,不再插入
		return 0;
	}
}

// 算法9.8 P231
// 从二叉排序树中删除结点p,并重接它的左或右子树。
void Delete(BiTree *p)
{
	// 中介,辅助删除结点
	BiTree q, s;
	
	if( !(*p)->rchild )
	{
		// 右子树空则只需重接它的左子树(待删结点是叶子也走此分支)
		q = *p;
		*p = (*p)->lchild;
		free(q);
	}
	else if( !(*p)->lchild )
	{
		// 左子树为空则只需重接它的右子树
		q = *p;
		*p = (*p)->rchild;
		free(q);
	}
	else
	{
		// 左右子树均不空
		
		// 转左,然后向右到尽头,找待删结点的前驱
		q = *p;
		s = (*p)->lchild;
		while(s->rchild)
		{
			q = s;
			s = s->rchild;
		}
		
		// s指向被删结点的"前驱"(将被删结点前驱的值取代被删结点的值)
		(*p)->data = s->data;
		if(q != *p)
			q->rchild = s->lchild; // 重接*q的右子树
		else
			q->lchild = s->lchild; // 重接*q的左子树
		free(s);
	}
}

// 算法9.7 P230
// 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点,
// 并返回1;否则返回0。
int DeleteBST(BiTree *T, KeyType key)
{	
	if(!*T) // 不存在关键字等于key的数据元素
		return 0;
	else
	{
		if(key == (*T)->data.key) // 找到关键字等于key的数据元素
			Delete(T);
		else if(key < (*T)->data.key)
			DeleteBST(&(*T)->lchild,key);
		else
			DeleteBST(&(*T)->rchild,key);
		return 1;
	}
}

// 按关键字的顺序对DT的每个结点调用函数Visit()一次
void TraverseDSTable(BiTree DT, void(*Visit)(ElemType))
{
	if(DT)
	{
		// 像这样遍历,最后结果是个非递减顺序
		TraverseDSTable(DT->lchild,Visit); // 先中序遍历左子树
		Visit(DT->data); // 再访问根结点
		TraverseDSTable(DT->rchild,Visit); // 最后中序遍历右子树
	}
}

void print(ElemType c)
{
	printf("(%d,%d) ", c.key, c.others);
}

int main()
{
	BiTree dt,p;
	int i;
	KeyType j;
	
	// 以教科书P227图9.7(a)为例
	ElemType r[N] =
	{
		{45,1}, {12,2}, {53,3}, {3,4}, {37,5},
		{24,6}, {100,7}, {61,8}, {90,9}, {78,10}
	};

	// 构造空表
	InitDSTable(&dt);

	// 依次插入数据元素
	for(i = 0; i < N; i++)
		InsertBST(&dt, r[i]);
	
	TraverseDSTable(dt,print);
	
	printf("\n请输入待查找的值: ");
	scanf("%d", &j);
	p = SearchBST(dt,j);
	if(p)
	{
		printf("表中存在此值。");
		DeleteBST(&dt,j);
		printf("删除此值后:\n");
		TraverseDSTable(dt,print);
		printf("\n");
	}
	else
	{
		printf("表中不存在此值\n");
	}
	
	DestroyDSTable(&dt);
	
	return 0;
}

/*
输出效果:

(3,4) (12,2) (24,6) (37,5) (45,1) (53,3) (61,8) (78,10) (90,9) (100,7)
请输入待查找的值: 45
表中存在此值。删除此值后:
(3,4) (12,2) (24,6) (37,5) (53,3) (61,8) (78,10) (90,9) (100,7)

*/

抱歉!评论已关闭.