数据结构_二叉查找树

                坚持,做一件事不难,难的是,一直坚持做一件事!在这中间,肯定有这个那个的牵绊,但自己的目标要明确,一直努力。

// 数据结构_二叉查找树.cpp : Defines the entry point for the console application.
//

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

 

typedef struct TWOTREE{
 
 TWOTREE *p;
 TWOTREE *left;
 TWOTREE *right;
 int  key;
}TWOTREE,*PTWOTREE;


/*查找树是一种数据结构,它支持多种动态集合操作,包括SEARCH,
MINIMUM,MAXIMUN,PREDECESSOR,SUCCESSOR,INSERT,DELETE,它既可以用作字典,也可以用作优先队列
二叉查找树上执行的基本操作的时间和树的高度成正比,对于一颗含有N个结点的完全二叉树
这些操作的基本时间为lgN,如果树是含有N个结点的线性链,则这些操作的最坏情况运行时间为N*/

/*
算法导论中的二叉查找树插入的伪代码
TREE-INSERT(T,z)
1 y <- NIL
2 x <- root(T)

//3-8行,我们第一次初始化根结点的时候,其左右儿子结点和父结点都为NULL,插入第一个数时,只执行一次
//第二次执行时,根结点或左或右儿子结点肯定不为NULL,插入的结点除了跟结点比较,还可能跟插入的结点比较,前提是第二次结点
跟第一次结点一样,比根结点小,或者大。
3 while x != NIL
4     do y <- x
5  if key[z] < key[x]
6   then x <- left[x]
7   else x <- right[x]
这里的y有保存x结点的值,不管此时结点z的key值是小于y的key,还是大于y的key,z的父结点肯定是y.
8 p[z] <- y
9   if y = NIL  这里当为空树时,此时根结点也为NULL,直接将第一个值z当成根结点
10     then root[T] <- z
11  else if key[z] < key[y] 刚才只设置了,z的父结点,这里还要设置y的左右儿子结点,是左还是右,key值决定。
12   then left[y] <- z
13   else right[y] <- z
*/

int tree_insert(TWOTREE *root,TWOTREE *z){

 PTWOTREE x = NULL,y = NULL;

 x = root;

 while(x != NULL){

  y = x;

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

   x = x->left;
  }
  else{

   x = x->right;
  } 
 }

 z->p = y;

 if(NULL == y){

  root = z;
 }
 else if(z->key < y->key){

  y->left = z;
 }
 else{
  
  y->right = z;
 }

 return 0;
}

/*二叉查找树,中序遍历伪代码
INORDER-TREE-WALK(x)
1 if x != NULL
2    then INORDER-TREE-WALK(left[x])
3 print key[x]
4  INORDER-TREE-WALK(right[x])

*/

int inorder_tree_walk(TWOTREE *x){
 
 if(x != NULL){
  
  inorder_tree_walk(x->left);
  printf("%d ",x->key);
  inorder_tree_walk(x->right);
 }
 
 return 0;
}

/*
查询二叉查找树
TREE-SEARCH(x,k)
1 if x=NIL or k = key[x]
2 then return x
3 if k < key[x]
4 then return TREE-SEARCH(left[x],k)
5 else return TREE-SEARCH(right[x],k)
*/

/*
ITERATIVE-TREE-SEARCH(x,k)
1 while x != NIL and k != key[x]
2 do if k < key[x]
3  then x <- left[x]
4  else x <- right[x]
5 return x
*/

TWOTREE *interative_tree_search(TWOTREE *x,int k){

 while((NULL != x) &&(k != x->key)){

  if (k < x->key){

   x = x->left;
  }
  else{

   x = x->right;
  }

 }

 return x;
}
/*最小元素的寻找
TREE-MINIMUN(x)
1 while left[x] != NIL
2  do x <- left[x]
3  return x
*/

TWOTREE *tree_minimum(TWOTREE *x){

 while(NULL != x->left){

  x = x->left;
 }
 
 return x;
}
/*最大元素的寻找
TREE-MAXIMUM(x)
1 while right[x] != NIL
2  do x <- right[x]
3  return x
*/
TWOTREE *tree_maximum(TWOTREE *x){
 
 while(NULL != x->right){
  
  x = x->right;
 }
 
 return x;
}

/*
前趋和后继
给定一个二叉查找树结点,有时候要求找出中序遍历顺序下它的后继,如果所有的关键字都不相同
则某一结点的后继即具有大于key[x]中的关键字中最小者的那个结点,根据二叉查找树的结构,不用对关键字做任何比较,就
可以找到某个结点的后继
TREE-SUCCESSOR(x)
1 if right[x] != NIL 如果x结点的右子树不为空,x结点的后继就是右子树中的最左结点
2 then return TREE-MINIMUM(right[x])
3 y <- p[x]
4 while y != NIL and x = right[y] 为了找到,一个结点,它的左儿子是y的父结点
5 do x <- y
6  y <- p[y]
7 return y
*/
TWOTREE *tree_successor(TWOTREE *x){

 PTWOTREE y = NULL;

 if(x->right != NULL){

  return tree_minimum(x->right);// x 的右子树的最左孩子就是x的后继
 }

 y = x->p;// x结点没有右子树,如果x是其父结点的左孩子,直接返回x的父结点

 while((y != NULL) &&(x == y->right)){//如果x结点,是其父结点的右孩子,一直要找一个,其父结点是要找结点的左孩子。返回这个结点

  x = y;

  y = y->p;
 }

 return y;
}

/*
删除,将给定结点z从二叉查找树中删除的过程以指向z的指针为参数
并考虑三中情况
如果z没有子女,则修改其父结点p[z],使其左或右子女为NIL,如果结点z只有一个子女,则可以通过在其父结点间建立一条链
来删除z,最后如果结点z有两个子女,则先删除z的后继y(它没有左子女),再用y的内容来替代z的内容
TREE-DELETE(T,z)
1 if left[z] = NIL or right[z] = NIL
2    then y <- z
3  else y <- TREE-SUCCESSOR(z)
4 if left[z] != NIL
5  then x <- left[y]
6  else x <- right[y]
7 if x != NIL
8    then p[x] <- p[y]
9 if p[y] = NIL
10   then root[T] <- x
11   else if y = left[p[y]]
12    then left[p[y]] <- x
13  else right[p[y]] <- x
14 if y != z
15   then key[z] <- key[y]
16     copy y's satellite data inti z
17 return y
*/
TWOTREE *tree_delete(TWOTREE *root,TWOTREE *z){

 PTWOTREE y = NULL,x = NULL;

 // 如果待删除的结点,有一个孩子

 if((z->left == NULL) || (z->right == NULL)){

  y = z;
 }
 else{
    // 如果结点有两个孩子,找到z的后继为y
  y = tree_successor(z);
 }
 if(z->left != NULL){
        // y可能是z的后继,或者y=z;
  x = y->left;
 }
 else{
        // y不可能是z的后继,因为z->left为NULL,此时x可以为NULL,或者不为NULL.
  x = y->right;
 }
 if( x != NULL){
  
  x ->p = y->p; //x 的父结点等于y的父结点,如果是后继并且后继有左孩子,就将后继左孩子的父结点等于后继的父结点
 }
 if(y->p == NULL){

  root = x; // 父结点为NULL ,必定是根结点。
 }
 else if(y == y->p->left){//如果y是其父结点的左孩子

  y->p->left = x;  //就将y的父结点的左孩子设置成x
 }
 else{

  y->p->right = x;//就将y的父结点的右孩子设置成x 
 }
 if(y != z){// 如果z有两个孩子,就需要将z后继拷贝到z的位置。

  z->key = y->key;

 }

 return y;
}

int main(int argc, char* argv[])
{
 PTWOTREE root = NULL;

 PTWOTREE z;

 PTWOTREE ptemp;

 int a[] = {12,5,2,9,18,15,19,13,17};

 int i = 0;

 root = (TWOTREE *)malloc(sizeof(PTWOTREE));
   
 root->p = NULL;

 root->key = a[0];

 root->left = NULL;
 
 root->right = NULL;

 for(i = 1; i < 9;i++){
   
        z = (TWOTREE *)malloc(sizeof(PTWOTREE));

  z->key = a[i];

  z->p = NULL;

  z->left = NULL;

  z->right = NULL;

  tree_insert(root,z);

 }

    inorder_tree_walk(root);

 ptemp = tree_delete(root,root->left);

 printf("\n");

 inorder_tree_walk(root);

    ptemp = interative_tree_search(root,17);

    ptemp = tree_minimum(root);

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

 ptemp = tree_maximum(root);

 printf("maximun %d\n",ptemp->key);
 
 ptemp = tree_maximum(root->right->left);

 printf("houji %d",ptemp->key);

 return 0;
}

            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值