二叉树操作

二叉树操作

实验目的

实现如下二叉树操作,Input:1-n的数组

(1)通过插入操作建立二叉树

(2)实现查找、最大/小关键字查询

(3)从1到n的依次删除

 

实验原理

二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比。二叉搜索树可以使用一个链表数据结构来表示,其中每个结点都是一个对象。每个结点包含属性key,left,right,p,它们分别指向结点的关键字,左孩子,右孩子和双亲。如果某个孩子结点和父亲结点不存在,则相应属性值为NIL。

二叉搜索树中关键字满足二叉搜索树性质:设x是二叉搜索树中的一个结点,如果y是x左子树中的一个结点,那么y.key <= x.key;如果y是x右子树中的一个结点,那么y.key >= x.key。

 

实验过程

(一)插入法建立二叉树

要将一个新值v插入到一棵二叉搜索数T中,需要调用过程TREE-INSERT。该过程以结点z作为输入,其中z.key = v, z.left = NIL, z.right = NIL。

TREE-INSERT(T, z)

1 y = NIL

2 x = T.root

3 while x != NIL

4     y = x

5     if z.key < x.key

6          x = x.left

7     else x = x.right

8 z.p = y

9 if y == NIL

10       T.root = z

11 elseif z.key < y.key

12       y.left = z

13 else y.right = z

 

(二)实现查找、最大/小关键字查询

查找:输入一个指向树根的指针和一个关键字k,如果这个结点存在,TREE-SEARCH返回一个指向关键字k的节点的指针;否则返回NIL。

 

TREE-SEARCH(x, k)

1 if x == NIL or k == x.key

2    return x

3 if k < x.key

4    return TREE-SEARCH(x.left, k)

5 else return TREE-SEARCH(x.right, k)

 

最大关键字元素和最小关键字元素:通过从树根开始沿着left孩子指针直到遇到一个NIL,返回一个指向在以给定结点x为根的子树中的最小元素的指针;通过从树根开始沿着right孩子指针直到遇到一个NIL,返回一个指向在以给定结点x为根的子树中的最小元素的指针。

TREE-MINIMUM(x)

1 while x.left != NIL

2    x = x.left

3 return x

 

TREE-MAXIMUM(x)

1 while x.right != NIL

2    x = x.right

3 return x

 

(三)实现删除

从一棵二叉搜索树T中删除一个结点z的整个策略分为三种基本情况:

1)如果z没有孩子结点,那么只是简单地将它删除,并修改它的父结点,孩子结点指向NIL;

2)如果z只有一个孩子,那么将这个孩子提升到树中z的位置上,用z的孩子来替换z;

3)如果z有两个孩子,那么先找到z的后继结点y,如果y是z的右孩子,那么用y替换z,并仅留下y的右孩子;如果,y位于z的右子树中但并不是z的右孩子,先用y的右孩子替换y,然后再用y替换z;

定义一个过程TRANSPLANT,它是用另一棵子树替换一棵子树并成为其双亲的孩子结点:

TRANSPLANT(T, u, v)

1 if u.p == NIL

2    T.root = v

3 elseif u == u.p.left

4    u.p.left = v

5 else u.p.right = v

6 if v != NIL

7    v.p = u.p

 

TREE-DELETE(T, z)

1 if z.left == NIL

2    TRANSPLANT(T, z, z.right)

3 elseif z.right == NIL

4    TRANSPLANT(T, z, z.left)

5 else y = TREE-MINIMUM(z.right)

6    if y.p != z

7        TRANSPLANT(T, y, y.right)

8        y.right = z.right

9        y.right.p = y

10   TRANSPLANT(T, z, y)

11   y.left = z.left

12   y.left.p = y

实验总结

(一)二叉搜索树优点在于,在树上的基本操作与这棵树的高度成正比:对于一棵有n个结点的完全二叉树,在树上操作的最坏运行时间是Θ(lgn)。然而,如果树是一条n个结点组成的线性链,那么同样的操作就要花费Θ(n)的最坏运行时间。

(二)针对在构建树的过程中,出现最坏情况导致线性链的发生,可采取几种处理方式:可通过随机构建二叉搜索树;还可以设计二叉树的变体,即红黑树,红黑树的树高为O(lgn);还可以使用B树。

(三)二叉搜索树是学习树的基础,为了充分利用二叉搜索树的优点,避免二叉树的最坏情况,从而研究出来了红黑树和B树。

 

附录(代码)

#include <stdio.h>

#include <stdlib.h>

 

typedef struct node *tree_pointer;

typedef struct node{

    int key;

    tree_pointerp;

    tree_pointerleft;

    tree_pointerright;

} *tree_pointer;

 

void tree_insert(tree_pointer z);

void print_tree(tree_pointer T_root, int n);

void transplant(tree_pointer T_root, tree_pointer u,tree_pointer v);

void tree_delete(tree_pointer T_root, tree_pointer z);

struct node * creat_node(int key);

struct node * tree_search(tree_pointer T_root, intkey);

struct node * tree_minimum(tree_pointer T_root);

struct node * tree_maximum(tree_pointer T_root);

int get_tree_height(tree_pointer T_root);

 

tree_pointer T_Root = NULL;

 

int main(){

   

    inti,key,node_number,tree_height,search_key,delete_key;

   

    tree_pointernew=NULL;

    tree_pointersearch_result;

    tree_pointerminimum;

    tree_pointermaximum;

    tree_pointerdelete;

 

    printf("pleaseinput the number of nodes:");

    scanf("%d",&node_number);

    for(i = 0; i< node_number; i++ ){

       printf("inputthe key:");

       scanf("%d",&key);

       new =creat_node(key);

       tree_insert(new);

       tree_height= get_tree_height(T_Root);

       print_tree(T_Root,tree_height);

    }

    printf("thefinal tree:\n");

    tree_height =get_tree_height(T_Root);

    print_tree(T_Root,tree_height);

   

    printf("\n");

    minimum =tree_minimum(T_Root);

    maximum =tree_maximum(T_Root);

    printf("Inthis tree, the minimum number is:");

    printf("%d\n",minimum->key);

    printf("Inthis tree, the maximum number is:");

    printf("%d\n",maximum->key);

 

    printf("\n");

    printf("whichkey do you want to search?\nplease input it:");

    scanf("%d",&search_key);

    printf("thesearching result: ");

    search_result= tree_search(T_Root, search_key);

    printf("(%p)and this (%p) refers to %d\n",search_result,search_result,search_result->key);

   

    printf("\n");

    printf("pleaseinput the node that you want to delete:");

    scanf("%d",&delete_key);

    printf("delete_key= %d\n",delete_key);

    delete =tree_search(T_Root, delete_key);

    printf("wewill delete:(%p) and it refers to %d\n", delete,delete->key);

    printf("deletethe node and print the tree:\n");

    tree_delete(T_Root,delete);

    tree_height =get_tree_height(T_Root);

    print_tree(T_Root,tree_height);

    return 0;

}

 

void tree_insert(tree_pointer z){

    tree_pointerx;

    tree_pointery = NULL;

    x = T_Root;

   

    while(x !=NULL){

       y = x;

       if(z->key< x->key)

           x =x->left;

       else

           x =x->right;

    }

    z->p = y;

    if(y == NULL)

       T_Root   = z;

    elseif(z->key < y->key)

       y->left  = z;

    else

       y->right= z;

   

}

 

void print_tree(tree_pointer T_root, int n){

    int i;

    if(T_root ==NULL)

       return;

    print_tree(T_root->right,n-1);

 

    for(i = 0; i< n-1; i++)

       printf("   ");

    if(n > 0){

       printf("---");

       printf("%d\n",T_root->key);

    }

   

    print_tree(T_root->left,n-1);

}

 

struct node * creat_node(int key){

    tree_pointernew;

    new = (structnode *)malloc(sizeof(struct node));

    new->key   = key;

    return new;

}

 

int get_tree_height(tree_pointer T_root){

    if(!T_root)

       return 0;

    intleft_height,right_height;

    left_height  = get_tree_height(T_root->left);

    right_height= get_tree_height(T_root->right);

    return(left_height < right_height)?(right_height+1):(left_height+1);

}

 

struct node * tree_search(tree_pointer T_root, intkey){

    while((T_root!= NULL) && (key != T_root->key)){

       if(key< T_root->key)

           T_root= T_root->left;

       else

           T_root= T_root->right;

    }

    returnT_root;

}

 

struct node * tree_minimum(tree_pointer T_root){

    while(T_root->left!= NULL)

       T_root =T_root->left;

    returnT_root;

}

 

struct node * tree_maximum(tree_pointer T_root){

    while(T_root->right!= NULL)

       T_root =T_root->right;

    returnT_root;

}

 

void transplant(tree_pointer T_root, tree_pointer u,tree_pointer v){

    if(u->p ==NULL)

       T_root =v;

    else if(u ==u->p->left)

       u->p->left  = v;

    else

       u->p->right= v;

    if(v != NULL)

       v->p =u->p;

}

 

void tree_delete(tree_pointer T_root, tree_pointer z){

    tree_pointery=NULL;

 

    if(z->left== NULL)

       transplant(T_root,z , z->right);

    elseif(z->right == NULL)

       transplant(T_root,z , z->left);

    else{

       y =tree_minimum(z->right);

       if(y->p!= z){

           transplant(T_root,y , y->right);

           y->right    = z->right;

           y->right->p= y;

       }

        transplant(T_root, z , y);

       y->left    = z->left;

       y->left->p= y;

    }

}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值