二叉查找树带父节点指针的创建,销毁,查找,删除,插入,找前驱后继,找最小值最大值(递归和非递归的实现)
2014-04-09 17:02
1061 查看
#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<time.h> typedef int bool ; #define true 1 #define false 0 #define SWAP(x,y,t) ((t=x),(x=y),(y=t)) #define INT #ifdef CHAR typedef char DataType; #else typedef int DataType ; #endif typedef struct Node { DataType data; struct Node *lchild; struct Node *rchild; struct Node *parent; } BSTNode ,* pBSTNode ; void InsertBST(pBSTNode *root,DataType x); bool Delete_x_BST(pBSTNode *root,DataType x); //两个都是删除节点元素但是一个是提供要删除元素的指针,另一个是要删除的元素 void DeleteBST(pBSTNode *root,pBSTNode p ,DataType *x); pBSTNode SearchBST(pBSTNode root ,DataType x); pBSTNode SearchMaxBST(pBSTNode root); pBSTNode SearchMaxBST2(pBSTNode root); pBSTNode SearchMinBST(pBSTNode root); pBSTNode SearchMinBST2(pBSTNode root); pBSTNode SearchPredecessor(pBSTNode p); pBSTNode SearchSuccessor(pBSTNode p); pBSTNode CreateBST(); void Visit(DataType data); void DestroyBST( pBSTNode root); void PreOrderTraverseBST(pBSTNode root); void InOrderTraverseBST(pBSTNode root); void InsertBST(pBSTNode *root,DataType x) { pBSTNode ptr=(pBSTNode) malloc(sizeof(BSTNode) ) ; ptr->data=x; ptr->lchild=NULL; ptr->rchild=NULL; ptr->parent=NULL; if(! *root) { *root =ptr; return ; } pBSTNode cur=*root; pBSTNode pre=cur; while ( cur) { pre=cur; if(cur->data<x ) { cur=cur->rchild; } // else if(p->data ==x) // { // printf(" insert the %d is not illegal,BST mustn't have the same key\n "); // exit(-1); // } else { cur=cur->lchild; } } if( pre->data <x) { pre->rchild=ptr; ptr->parent=pre; } else { pre->lchild=ptr; ptr->parent=pre; } } /* * *根据某个节点的指针,删除某个元素,并传回它的值 * * */ void DeleteBST(pBSTNode *root,pBSTNode p ,DataType *x) { if( !p) { printf("the list is null\n "); exit(-1); } else { *x=p->data; if(p->lchild==NULL && p->rchild==NULL) //待删除节点为叶子节点时 { if( p->parent ==NULL) //只有一个节点时,根节点发生变化 { *root=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=NULL; } else if(p==p->parent->rchild) { p->parent->rchild=NULL; } } free(p) ; } else if(p->lchild==NULL&& p->rchild!=NULL) //待删除节点左子树为空,右子树不为空 { if(p->parent==NULL) //待删除节点为根节点时 { *root=p->rchild; p->rchild->parent=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=p->rchild; p->rchild->parent=p->parent; } else { p->parent->rchild=p->rchild; p->rchild->parent=p->parent; } } free(p); } else if( p->lchild!=NULL && p->rchild==NULL) //待删除节点左子树不为空,右子树为空 { if(p->parent==NULL) //待删除节点为根节点时 { *root=p->lchild; p->lchild->parent=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=p->lchild; p->lchild->parent=p->parent; } else { p->parent->rchild=p->lchild; p->lchild->parent=p->parent; } } free(p); } else //左右子树都存在的时候 { pBSTNode q=SearchSuccessor(p); //或者是该节点的前驱,由于前驱节点或者后继节点为左子树的最大节点或者为右子树的最小节点 //则前驱或者后继节点的度必为0或1,由于这个结论我们就可以递归调用Delete_x_BST DataType temp; SWAP(p->data,q->data,temp) ; if(q->lchild==NULL && q->rchild==NULL) //待删除节点为叶子节点时 { if( q->parent ==NULL) //只有一个节点时,根节点发生变化 { *root=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=NULL; } else { q->parent->rchild=NULL; } } free(q) ; } else if(q->lchild==NULL&& q->rchild!=NULL) //待删除节点左子树为空,右子树不为空 { if(q->parent==NULL) //待删除节点为根节点时 { *root=q->rchild; q->rchild->parent=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=q->rchild; q->rchild->parent=q->parent; } else { q->parent->rchild=q->rchild; q->rchild->parent=q->parent; } } free(q) ; } else if( q->lchild!=NULL && q->rchild==NULL) //待删除节点左子树不为空,右子树为空 { if(q->parent==NULL) //待删除节点为根节点时 { *root=q->lchild; q->lchild->parent=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=q->lchild; q->lchild->parent=q->parent; } else { q->parent->rchild=q->lchild; q->lchild->parent=q->parent; } } free(q) ; } } } } /* * *删除关键字为x的节点 * * */ bool Delete_x_BST(pBSTNode *root,DataType x) { pBSTNode p=SearchBST(*root ,x) ; if(!p) { printf("没有值为x的节点或者二叉树为空(不过二叉树为空也是没有值为x的节点的情况)\n"); return false; } else { if(p->lchild==NULL && p->rchild==NULL) //待删除节点为叶子节点时 { if( p->parent ==NULL) //只有一个节点时,根节点发生变化 { *root=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=NULL; } else if(p==p->parent->rchild) { p->parent->rchild=NULL; } } free(p) ; } else if(p->lchild==NULL&& p->rchild!=NULL) //待删除节点左子树为空,右子树不为空 { if(p->parent==NULL) //待删除节点为根节点时 { *root=p->rchild; p->rchild->parent=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=p->rchild; p->rchild->parent=p->parent; } else { p->parent->rchild=p->rchild; p->rchild->parent=p->parent; } } free(p); } else if( p->lchild!=NULL && p->rchild==NULL) //待删除节点左子树不为空,右子树为空 { if(p->parent==NULL) //待删除节点为根节点时 { *root=p->lchild; p->lchild->parent=NULL; } else { if(p==p->parent->lchild) { p->parent->lchild=p->lchild; p->lchild->parent=p->parent; } else { p->parent->rchild=p->lchild; p->lchild->parent=p->parent; } } free(p); } else //左右子树都存在的时候 { pBSTNode q=SearchSuccessor(p); //或者是该节点的前驱,由于前驱节点或者后继节点为左子树的最大节点或者为右子树的最小节点 //则前驱或者后继节点的度必为0或1,由于这个结论我们就可以递归调用Delete_x_BST DataType temp; SWAP(p->data,q->data,temp) ; //Delete_x_BST( &*root ,q->data); 但是递归调用会出现问题,如果节点元素相同时,但是带有卫星数据时,删除的数据不是我们要删除的数据 if(q->lchild==NULL && q->rchild==NULL) //待删除节点为叶子节点时 { if( q->parent ==NULL) //只有一个节点时,根节点发生变化 { *root=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=NULL; } else { q->parent->rchild=NULL; } } free(q) ; } else if(q->lchild==NULL&& q->rchild!=NULL) //待删除节点左子树为空,右子树不为空 { if(q->parent==NULL) //待删除节点为根节点时 { *root=q->rchild; q->rchild->parent=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=q->rchild; q->rchild->parent=q->parent; } else { q->parent->rchild=q->rchild; q->rchild->parent=q->parent; } } free(q) ; } else if( q->lchild!=NULL && q->rchild==NULL) //待删除节点左子树不为空,右子树为空 { if(q->parent==NULL) //待删除节点为根节点时 { *root=q->lchild; q->lchild->parent=NULL; } else { if(q==q->parent->lchild) { q->parent->lchild=q->lchild; q->lchild->parent=q->parent; } else { q->parent->rchild=q->lchild; q->lchild->parent=q->parent; } } free(q) ; } } return true ; } } pBSTNode SearchBST(pBSTNode root ,DataType x) { if(! root) return NULL; if(root->data==x) return root; else if(root->data < x ) return SearchBST(root->rchild , x); else return SearchBST(root->lchild , x); } /* *查找二叉查找树最大值的递归形式 * * */ pBSTNode SearchMaxBST(pBSTNode root) { if(!root) return NULL; else if(root->rchild==NULL) return root ; else return SearchMaxBST(root->rchild) ; } /* * *查找二叉查找树的最大值 非递归形式 * * */ pBSTNode SearchMaxBST2(pBSTNode root) { if( !root) return NULL; else { pBSTNode cur=root; pBSTNode pre=cur; while(cur) { pre=cur; cur=cur->rchild; } return pre; } } /* *查找二叉查找树最小值递归形式 * * */ pBSTNode SearchMinBST(pBSTNode root) { if(!root) return NULL; else if (root->lchild==NULL) return root; else return SearchMinBST(root->lchild) ; } /* *查找二叉查找树最小值非递归形式 * * */ pBSTNode SearchMinBST2(pBSTNode root) { if(!root) return NULL; else { pBSTNode cur=root; pBSTNode pre=cur; while( cur) { pre=cur; cur=cur->lchild; } return pre; } } /* * *查找某个节点的前驱 * * */ pBSTNode SearchPredecessor(pBSTNode p) { if(!p) { printf("the input is null.don't have the Predecessor\n ") ; exit(-1); } else { if( p->lchild==NULL) { pBSTNode pre=p->parent; //父节点 while(pre) { if(pre->rchild==p) //如果父节点是爷爷节点的有孩子则爷爷节点就是前驱 { return pre; } else { p=pre; pre=pre->parent; } } return NULL; } else { return SearchMaxBST(p->lchild) ; //如果左子树存在,前驱为左子树的最大值节点 } } } pBSTNode SearchSuccessor(pBSTNode p) { if( !p) { printf("the input is null. don't have the predecessor\n"); exit(-1); } else { if( p->rchild ==NULL) { pBSTNode pre=p->parent; while( pre) { if(pre->lchild==p) { return pre; } else { p=pre; pre=pre->parent; } } return NULL; } else { return SearchMinBST(p->rchild); } } } /* pBSTNode CreateBST() { int i; int a[10]; pBSTNode T=NULL; srand( (unsigned int) time(NULL) ) ; for ( i=0 ;i<10 ;i++) a[i]=rand()%30; printf("the original data:\n"); for ( i=0 ;i<10 ;i++) printf("%d ",a[i]); printf("\n"); for( i=0 ;i<10 ;i++) InsertBST(&T ,a[i]) ; return T; } */ pBSTNode CreateBST() { int i; int a[8]={4,7,8,2,3,5,6,9}; pBSTNode T=NULL; printf("the original data:\n"); for ( i=0 ;i<8 ;i++) printf("%d ",a[i]); printf("\n"); for( i=0 ;i<8 ;i++) InsertBST(&T ,a[i]) ; return T; } void Visit(DataType data) { printf(" %d ",data) ; } void PreOrderTraverseBST(pBSTNode root) { if(!root) return ; else { Visit(root->data); PreOrderTraverseBST(root->lchild) ; PreOrderTraverseBST(root->rchild) ; } } void InOrderTraverseBST(pBSTNode root) { if(!root) return ; else { InOrderTraverseBST(root->lchild) ; Visit(root->data) ; InOrderTraverseBST(root->rchild) ; } } void DestroyBST( pBSTNode root) { if( !root) return ; else { DestroyBST( root->lchild) ; DestroyBST( root->rchild) ; free(root) ; } } int main() { pBSTNode T=CreateBST() ; PreOrderTraverseBST(T) ; printf("\n"); InOrderTraverseBST(T) ; printf("\n"); int i=2; pBSTNode p=SearchBST( T ,i) ; if( p) { printf("\nyou search the %d .Success!\n",i); printf("\nso you receive the poniter,we can delete it\n"); DataType x; DeleteBST(&T,p,&x); printf("要删除的元素是%d \n",x); printf("after delete the %d\n",x); InOrderTraverseBST(T) ; printf("\n"); } else printf("\nyou can't search the %d.\n",i) ; pBSTNode predecessor=SearchPredecessor(p) ; if( predecessor) printf("\nthe predecessor is %d.\n",predecessor->data); else printf("\n%d don't have the predecessor\n",i) ; pBSTNode succesor=SearchSuccessor(p) ; if( succesor) printf(" \nthe successor is %d.\n" ,succesor->data); else printf(" \n%d don't have the successor\n",i ) ; DataType del_num=5; if( Delete_x_BST(&T ,del_num) ) { printf("要删除的元素是%d \n",del_num); printf("after delete the %d\n",del_num); InOrderTraverseBST(T); printf("\n"); } p=SearchMaxBST(T) ; if (p) printf("the BST's MAX 递归形式 is %d\n", p->data) ; p=SearchMaxBST2(T) ; if (p) printf("the BST's MAX 非递归形式 is %d\n" , p->data) ; p=SearchMinBST(T) ; if(p) printf("the BST's Min 递归形式 is %d\n" , p->data) ; p=SearchMinBST2(T) ; if (p) printf("the BST's Min 非递归形式 is %d\n" , p->data) ; DestroyBST(T); return 1; }
相关文章推荐
- (Swift 实现)二叉搜索树 —— 创建,最大,最小,查找,插入,删除,前驱,后继,中序遍历
- javascript实现二叉树的创建,遍历,添加,查找最大值最小值和指定值的寻找及删除功能——递归的多次运用
- 二叉树的遍历 插入 查找 删除 最大值 最小值 前驱 后继节点的查找
- 二叉搜索树(BST)递归与非递归的插入、删除、查找的实现
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- java实现创建链表以及插入节点,查找结点,删除节点等操作
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- Java实现二叉查找树的创建、查找、插入、删除、遍历
- (C语言)BinarySrearchTree二叉搜索树 --- 标准插入(递归,非递归)、遍历(前,中,后序)、查找(递归,非递归)、根插入递归(左旋,右旋)、最小最大值、删除节点
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 带有头指针的链表的 创建 输出 查找 删除 释放 排序(冒泡排序)功能实现(尾插法(自动记录最后一个节点))
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- c++实现二叉树的查找,插入,删除,深度,叶子节点数,度为1的节点数(递归方法)及运行实例结果
- 二叉搜索树的相关操作:插入节点,删除节点,排序,查找,最大值,最小值,前序,中序,后序遍历(主要用到递归的方法)
- 查找二叉树的实现(查找,删除,插入)分别用递归和非递归
- 二叉查找树的查找,插入,最大/最小值查找,前驱/后续查找,删除算法[java]
- 二叉查找树前驱、后继,非递归不使用栈不使用访问标记的中序遍历,最大最小节点