【算法导论】 二叉搜索树、AVL树、和红黑树

二叉搜索树

二叉搜索树是一颗二叉树或一颗空树且满足以下性质:

1)根节点 x的key值大于任意左子树上节点的key值,小于右子树上任意节点的key值 ;

2)其左右子树也分别是一颗二叉搜索树。

/**
 * zhanw15 @2018/4/12
 * 
 * filename: tree.h
 * 二叉搜索树,红黑树定义
 */ 

#include<stdlib.h>

typedef struct binaryTree
{
	int key;
	binaryTree *p;		//parent
	binaryTree *left;	//left_son
	binaryTree *right;	//right_son
}binaryTree;
/**
 * zhanw15 @2018/4/12
 * 算法导论 12章
 *
 * 二叉搜索树 @P286
 * filename: binaryTree.cpp
 *
 * @Operation = { Search, Min, Max, Delete, Insert,  PredecessOR, SuccessOR};
 */ 
#include <stdio.h>
#include "..\tree.h"

/* 访问节点 */ 
void visit( binaryTree *a)
{
	printf( "%d  ", a->key);
}

/* 中序遍历 时间复杂度 n */ 
void Inorder_Tree( binaryTree *a)
{
	if( a==NULL) return;
	
	Inorder_Tree( a->left);
	visit( a);
	Inorder_Tree( a->right);
}

/* 查找二叉搜索树 迭代版本*/
binaryTree *Tree_Search( binaryTree *a, int k)
{
	while( a!=NULL && a->key!=k) {
		if( a->key<k)
			a = a->right;
		else
			a = a->left;
	}
	return a;
} 

/* 获取二叉搜索树最大值节点 */
binaryTree *Tree_Min_Key( binaryTree *a)
{
	if( a==NULL) return a;
	//if( a->right==NULL) return a;
	//return a->right;
	//滥用递归不是个好习惯
	while( a->left!=NULL) a = a->left; 
	return a;
}

/* 获取二叉搜索树的最小值节点 */ 
binaryTree *Tree_Max_Key( binaryTree *a)
{
	if( a==NULL) return a;
	while( a->right!=NULL) a = a->right;
	return a;
}

// 在某一遍历次序下,得到最后的遍历结果,若x1、x2相邻,
// 且x1在x2前,则称x1是x2的前驱,x2是x1的后继 
 
/* 中序遍历下二叉搜索树的前驱 */
binaryTree *PredecessOR( binaryTree *a)
{
	if( a->left!=NULL) return Tree_Max_Key( a->left);
	
	while( a->p!=NULL && a->p->left==a) {
		a = a->p;
	}
	return a->p;
}

/* 中序遍历下二叉搜索树的后继 */
binaryTree *SuccessOR( binaryTree *a)
{
	if( a->right!=NULL) return Tree_Min_Key( a->right);
	
	while( a->p!=NULL && a->p->right==a) {
		a = a->p;
	}
	return a->p;
} 

/* 插入节点 时间复杂度: h(树高度) */
binaryTree *Tree_Insert( binaryTree *Head, binaryTree *a)
{
	if( a==NULL) return Head;
	
	//找到插入节点的位置 
	binaryTree *t = Head, *temp = Head;
	while( t!=NULL) {
		temp = t;
		if( t->key>a->key) t = t->left;
		else t = t->right;
	}
	
	//插入节点 
	if( temp==NULL) Head = a;
	else if( a->key > temp->key) {
		temp->right = a;
	}
	else {
		temp->left = a;
	}
	a->p = temp;
	
	return Head; 
} 

/* 将u位置子树替换为v子树 */ 
binaryTree *Transplant( binaryTree *Head, binaryTree *u, binaryTree *v)
{
	
	if( u->p==NULL) Head = v;
	else {
		if( u==u->p->left)
			u->p->left = v;
		else
			u->p->right = v;
	}
	if( v!=NULL) v->p = u->p;
	
	return Head;
}

/* 删除节点 时间复杂度: h*/ 
binaryTree *Tree_Delete( binaryTree *Head, binaryTree *a)
{
	if( a==NULL) return Head;
	
	//若节点左或右无子树,则拿右或左子树替换掉当前节点 
	if( a->left==NULL)	Head = Transplant( Head, a, a->right);
	else if( a->right==NULL) Head = Transplant( Head, a, a->left);
	else { 
		// 若左右子树均存在,则使用其后继替换此节点 
		binaryTree *y = Tree_Min_Key( a->right);
		/** 
		 *  若后继节点不是其右孩子,那么后继节点一定是其右子树的最小值,\
		 *  且其后继一定没有左子树(参看后继定义) 
		 */ 
		if( y->p!=a) {
			Head = Transplant( Head, y, y->right);
			y->right = a->right;
			y->right->p = y;
		}
		Head = Transplant( Head, a, y);
		y->left = a->left;
		y->left->p = y;
	}
	free( a);
	return Head;
}

int main()
{
	int a[17] = { 14, 32, 43, 4, 23, 7, 64, 13, \
	90, 70, 12, 24, 1, -4, 48, 22, 65};
	
	binaryTree *Head=NULL;
	
	for( int i=0; i<17; i++) {      //插入元素 
		binaryTree *temp = new binaryTree;
		(*temp) = { a[i], NULL, NULL, NULL};
		
		Head = Tree_Insert( Head, temp);
	}
	
	Inorder_Tree( Head);
	
	int k = 7;             //测试:查找、前驱、后继 
	printf( "\nkey = %d  Suce: %d  Pred: %d\n", k, SuccessOR\
	( Tree_Search( Head, k))->key, PredecessOR( Tree_Search( Head, k))->key);
	
	int k2 = 4;           //测试: 删除值为4的节点 
	Inorder_Tree( Head = Tree_Delete( Head, Tree_Search( Head, k2)));
	
	return 0;
}

// output: (mingw gcc 4.7.2 32-bit)
// -4  1  4  7  12  13  14  22  23  24  32  43  48  64  65  70  90
// key = 7  Suce: 12  Pred: 4
// -4  1  7  12  13  14  22  23  24  32  43  48  64  65  70  90

持续更新中。。。

猜你喜欢

转载自blog.csdn.net/zhanw15/article/details/79916907