二叉查找树

          在计算机科学中,二叉树是每个节点最多有两个子树树结构。通常子树被称作“左子树”(left subtree

和“右子树”(right subtree)。二叉树常被用于实现二叉查找树二叉堆


二叉查找树的C 语言实现如下:

分别有三部分:main.c   Head.h   fun.c


头文件Head.h 

#ifndef HEAD_H_
#define HEAD_H_

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

typedef int ElementType;
typedef struct TreeNode
{
	ElementType Element;
	struct TreeNode   *Left;
	struct TreeNode   *Right;
}*Position,*SearchTree;

SearchTree MakeEmpty(SearchTree T);
Position Find(ElementType x,SearchTree T);
Position FindMin(SearchTree T);
Position FindMax(SearchTree T);
SearchTree Insert(ElementType x,SearchTree T);
SearchTree Delete(ElementType x,SearchTree T);
ElementType Retrieve(Position P);
void PrintTree(SearchTree T);

#endif /* HEAD_H_ */


功能函数fun.c

#include"Head.h"
/*
 *  此操作主要用于初始化
 */
SearchTree MakeEmpty(SearchTree T)
{
	if(T!=NULL)
	{
		MakeEmpty(T->Left);
		MakeEmpty(T->Right);
		free(T);
	}
	return NULL;
}
/*
 *   Find  返回指向树T中具有关键字 x 的节点的指针,不存在则返回NULL。
 *   注意这里两个递归都是尾递归,所使用的栈空间 只有 O(log N)
 */
Position Find(ElementType x,SearchTree T)
{
	if(T == NULL)
		return NULL;
	if(x < T->Element)
		return Find(x,T->Left);
	else if(x > T->Element)
		return Find(x,T->Right);
	else
		return T;
}
/*
 *   FindMin  和  FindMax  分别返回树中最小元和最大元
 *   FindMin  采用 递归的方式
 *   FindMax  采用 非递归方式
 */
Position FindMin(SearchTree T)
{
	if(T == NULL)
		return NULL;
	if(T->Left == NULL)
		return T;
	else
		return FindMin(T->Left);
}
Position FindMax(SearchTree T)
{
	if(T != NULL)
		while(T->Right != NULL)
			T=T->Right;
	return T;
}
/*
 *   Insert 向树中插入元素,树中递归的向左右子树中插入
 */
SearchTree Insert(ElementType x,SearchTree T)
{
	if(T == NULL)    //当树为空时
	{
		// 创建节点
		T = (SearchTree)malloc(sizeof(struct TreeNode));
		if(T == NULL)
		{
			puts("out of space \n");
			exit(-1);
		}
		else
		{
			T->Element=x;
			T->Left=T->Right=NULL;
		}
	}
	else if(x < T->Element)   //插入左子树
	{
		T->Left=Insert(x,T->Left);
	}
	else                      //插入右子树
	{
		T->Right=Insert(x,T->Right);
	}
	//如果元素已经存在节点中,什么也不做
	return T;
}
/*
 *   删除树中某一个元素,分为以下情况
 *   1.树为空,返回NULL
 *   2.要删除的元素在左子树中,递归的在左子树中删除
 *   3.同理,要删除的元素在右子树中,递归的在右子树中删除
 *   4.找到要删除的元素,且节点只有一个孩子,或者没有孩子,是叶子
 *   5.找到要删除的元素,而且节点有两个孩子,此时最为复杂,
 *     (这种情况时,此种方法效率不高,因为要沿着树进行两次搜索)
 */
SearchTree Delete(ElementType x,SearchTree T)
{
	Position TmpCell;
	if(T == NULL)
		puts("Element not found \n");
	else if(x < T->Element)    //  x 在 左子树中
		T->Left=Delete(x,T->Left);
	else if(x > T->Element)    //  x 在 右子树中
		T->Right=Delete(x,T->Right);

	// 找到要删除的元素,而且节点有两个孩子
	else  if(T->Left && T->Right)
	{
		// 找到节点 T 的右子树中最小的节点,但这个节点元素是大于 T 的
		TmpCell=FindMin(T->Right);
		//将右子树中最小的但大于T的元素取代T,
		T->Element=TmpCell->Element;
		/*
		 * 递归的删除 T 的右子树中最小的元素,即刚取代T的那个节点,
		 * 第二次删除较容易,因为 T 的右子树中最小的节点元素没有 左孩子
		 */
		T->Right=Delete(T->Element,T->Right);
	}

	// 找到要删除的元素,但是节点只有一个孩子,或者没有孩子
	else
	{
		TmpCell=T;
		//如果节点 T->Left 的左孩子为空,则 T->Left 的父节点 绕过 该节点后删除
		if(T->Left == NULL)
			T=T->Right;
		//如果节点 T->Right 的右孩子为空,则 T->Right 的父节点 绕过 该节点后删除
		else if(T->Right == NULL)
			T=T->Left;
		free(TmpCell);
	}
	return T;
}
/*
 *   返回位置 p 的元素
 */
ElementType Retrieve(Position P)
{
	return  P->Element;
}
/*
 *   中序遍历  ,先是遍历左子树,在是当前节点,最后是右子树
 *   总的运行时间为  O(N)
 */
void PrintTree(SearchTree T)
{
	if(T != NULL)
	{
		PrintTree(T->Left);
		printf("%d \n",T->Element);
		PrintTree(T->Right);
	}
}

主函数main.c

#include"Head.h"

int main(void) {

    SearchTree T;
    Position P;
    int i;
    int j = 0;

    T = MakeEmpty( NULL );
    for( i = 0; i < 50; i++, j = ( j + 7 ) % 50 )
        T = Insert( j, T );
    PrintTree(T);

    for( i = 0; i < 50; i++ )
        if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i )
            printf( "Error at %d\n", i );

    for( i = 0; i < 50; i += 2 )
        T = Delete( i, T );
    puts("after delete:\n");
    PrintTree(T);

    for( i = 1; i < 50; i += 2 )
        if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i )
            printf( "Error at %d\n", i );
    for( i = 0; i < 50; i += 2 )
        if( ( P = Find( i, T ) ) != NULL )
            printf( "Error at %d\n", i );

    printf( "Min is %d, Max is %d\n", Retrieve( FindMin( T ) ),
               Retrieve( FindMax( T ) ) );
	return EXIT_SUCCESS;
}


你可能感兴趣的:(二叉查找树)