数据结构——二叉搜索树

一、定义

        二叉搜索树(binary search tree),又叫二叉查找树、二叉排序树。若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。

二、特性       

        在二叉搜索树中:

        1.若任意结点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值。

        2. 若任意结点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值。

        3.任意结点的左、右子树也分别为二叉搜索树。

三、操作

        BStree *insertBST(BStree *pBST,Elementtype value);//递归插入
        BStree *insertBST1(BStree *pBST,Elementtype value);//非递归插入 
        BStree *delBST(BStree *pBST,Elementtype value);//递归删除
        BStree *delBST1(BStree *pBST,Elementtype value);//非递归删除

        BStree *min(BStree *pBST);//取树中最小值 
        BStree *max(BStree *pBST);//取树中最大值
        void cleanBST(BStree **pBST);//清空树

        void Preordertraversal(BStree *pBST);//前序遍历
        void Inordertraversal(BStree *pBST);//中序遍历
        void Postordertraversal(BStree *pBST);//后续遍历

四、时间复杂度

        不论哪一种操作,所花的时间都和树的高度成正比。因此,如果共有n个元素,那么平均每次操作需要O(logn)的时间。

五、算法实现

        二叉排序树的操作主要有:

        1.查找:递归查找是否存在key。

        2.插入:原树中不存在key,插入key返回true,否则返回false。

        3.构造:循环的插入操作。

        4.删除:(1)叶子节点:直接删除,不影响原树。

        (2)仅仅有左或右子树的节点:节点删除后,将它的左子树或右子树整个移动到删除节点的位置就可以,子承父业。

        (3)既有左又有右子树的节点:找到须要删除的节点p左子树上的最大值或者右子树上的最小值,赋给p,然后删除该最大值或者最小值节点。

上代码:

 头文件:

#include <stdio.h>
#include <stdlib.h>
#ifndef BSTREE_H
#define BSTREE_H
typedef struct node BStree;
typedef int Elementtype;
struct node{
	Elementtype value;
	BStree *left;
	BStree *right;
};
#endif 
BStree *insertBST(BStree *pBST,Elementtype value);//递归插入
BStree *insertBST1(BStree *pBST,Elementtype value);//非递归插入 
BStree *delBST(BStree *pBST,Elementtype value);//递归删除
BStree *delBST1(BStree *pBST,Elementtype value);//非递归删除

BStree *min(BStree *pBST);//取树中最小值 
BStree *max(BStree *pBST);//取树中最大值
void cleanBST(BStree **pBST);//清空树

void Preordertraversal(BStree *pBST);
void Inordertraversal(BStree *pBST);
void Postordertraversal(BStree *pBST);

函数实现代码 :

#include "BStree.h"

//typedef struct node BStree;
//typedef int Elementtype;
//struct node{
//	Elementtype value;
//	BStree *left;
//	BStree *right;
//};

BStree *insertBST(BStree *pBST,Elementtype value){//递归插入
	if(!pBST){
		BStree *pNode=(BStree*)malloc(sizeof(BStree));
		pNode->value=value;
		pNode->left=pNode->right=NULL;
		pBST=pNode;
	}else{
		if(value<pBST->value){
			pBST->left=insertBST(pBST->left,value);
		}else if(value>pBST->value){
			pBST->right=insertBST(pBST->right,value);
		}
	}
	return pBST;
}
BStree *insertBST1(BStree *pBST,Elementtype value){//非递归插入 
	BStree *ptemp=pBST;
	BStree *pNode=(BStree*)malloc(sizeof(BStree));
	pNode->value=value;
	pNode->left=pNode->right=NULL;
	BStree *parent=NULL;
	if(!pBST){
		ptemp=pNode;
	}else{
		while(pBST){
			parent=pBST;
			if(value<pBST->value){
				pBST=pBST->left;
				if(!pBST) parent->left=pNode;
			}else if(value>pBST->value){
				pBST=pBST->right;
				if(!pBST) parent->right=pNode;
			}
		}
	}
	return ptemp;
}
BStree *delBST(BStree *pBST,Elementtype value){//递归删除 
	if(pBST){
		if(value<pBST->value){
			pBST->left=delBST(pBST->left,value);
		}else if(value>pBST->value){
			pBST->right=delBST(pBST->right,value);
		}else{
			if(pBST->left&&pBST->right){
				BStree *ptemp=min(pBST->right);
				pBST->value=ptemp->value;
				pBST->right=delBST(pBST->right,ptemp->value);
			}else if(!pBST->left){
				BStree *ptemp=pBST;
				pBST=pBST->right;
				free(ptemp);
			}else if(!pBST->right){
				BStree *ptemp=pBST;
				pBST=pBST->left;
				free(ptemp);
			}
		}
	}
	return pBST;
}
/*非递归删除,当找到欲删除结点ptemp时需同时记录父节点parent,删除后将parent和ptemp的后续节点链接*/
BStree *delBST1(BStree *pBST,Elementtype value){//非递归删除
	BStree *parent=NULL;
	BStree *ptemp=pBST;
	while(ptemp){//循环条件ptemp不为空,当欲删除值不存在则ptemp最终为空 
		parent=ptemp;//记录当前节点的父节点 
		if(value<ptemp->value){//value小于当前节点值,向左查找 
			ptemp=ptemp->left;
		}else if(value>ptemp->value){//反之向右查找 
			ptemp=ptemp->right;
		}
		if(ptemp&&ptemp->value==value){
		//ptemp不为空,且value等于当前节点值,需要考虑节点同时有左右子树,左子树为空,右子树为空三种情况 
			if(!ptemp->left){
				if(parent->left==ptemp){
					parent->left=ptemp->right;
					free(ptemp);
				}else if(parent->right==ptemp){
					parent->right=ptemp->right;
					free(ptemp); 
				}
			}else if(!ptemp->right){
				if(parent->left==ptemp){
					parent->left=ptemp->left;
					free(ptemp);
				}else if(parent->right==ptemp){
					parent->right=ptemp->left;
				}
			}else if(ptemp->left&&ptemp->right){
			//当同时有左右子树,可转换为删除右子树上的最小值或者左子树上的最大值 
				BStree *p=min(ptemp->right);
				ptemp->value=p->value;
				BStree *q=ptemp->right;
				parent=ptemp;
				while(q->value!=p->value){
					parent=q;
					q=q->left;
				}
				if(q==ptemp->right) parent->right=q->right;//父节点位于右子树上父节点为ptemp两种情况 
				else parent->left=q->right;
				free(q);break;//此种情况删除了其他节点代替了ptemp,需要break跳出循环。 
			}
		}
	}
	if(!ptemp){
		printf("删除值不存在\n");
	}
	return pBST;
} 


BStree *min(BStree *pBST){//取树中最小值 
	if(pBST){
		while(pBST->left){
			pBST=pBST->left;
		}
		return pBST;
	}
}
BStree *max(BStree *pBST){//取树中最大值
	if(pBST){
		while(pBST->right){
			pBST=pBST->right;
		}
		return pBST;
	}
}
void cleanBST(BStree **pBST){//清空树 
	if(*pBST){
		cleanBST(&(*pBST)->left);
		cleanBST(&(*pBST)->right);
		free(*pBST);*pBST=NULL;
	}
}
/*遍历验证程序*/
void Preordertraversal(BStree *pBST){
	if(pBST){
		printf("%d ",pBST->value);
		Preordertraversal(pBST->left);
		Preordertraversal(pBST->right);
	}
}
void Inordertraversal(BStree *pBST){
	if(pBST){
		Inordertraversal(pBST->left);
		printf("%d ",pBST->value);
		Inordertraversal(pBST->right);
	}
}
void Postordertraversal(BStree *pBST){
	if(pBST){
		Postordertraversal(pBST->left);
		Postordertraversal(pBST->right);
		printf("%d ",pBST->value);
	}
}

main函数 :

#include <stdio.h>
#include <stdlib.h>
#include "BStree.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	BStree *pBST=NULL;
	Elementtype value;
	scanf("%d",&value);
	while(value!=-1){
		pBST=insertBST1(pBST,value);
		scanf("%d",&value);
	}
	pBST=delBST(pBST,9);
	pBST=delBST1(pBST,5); 
	pBST=delBST1(pBST,9);
	Preordertraversal(pBST);printf("\n");
	Inordertraversal(pBST);printf("\n");
	Postordertraversal(pBST);printf("\n");
	cleanBST(&pBST);
	if(!pBST) printf("树已空\n"); 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值