二叉查找树

来源:互联网 发布:网络监控怎么设置 编辑:程序博客网 时间:2024/05/22 23:53

          在计算机科学中,二叉树是每个节点最多有两个子树树结构。通常子树被称作“左子树”(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);elsereturn T;}/* *   FindMin  和  FindMax  分别返回树中最小元和最大元 *   FindMin  采用 递归的方式 *   FindMax  采用 非递归方式 */Position FindMin(SearchTree T){if(T == NULL)return NULL;if(T->Left == NULL)return T;elsereturn 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;}


原创粉丝点击