二叉搜索树的随机化插入和伸展插入操作(平摊法)

源码例如以下:

#include <stdlib.h>
#include <stdio.h>
//#define Key int
#define hl h->l
#define hr h->r
#define hlr h->l->r
#define hll h->l->l
#define hrr h->r->r
#define hrl h->r->l
typedef int Key;
struct Item{
	Key key;
	char c;
};
typedef struct STnode* link;
struct STnode{
	Item item ; link l,r; int N;
};

static link head , z ;
static struct Item NULLitem ;

Key key(Item item){
	return item.key;
}
//创建一个节点
link NEW(Item item, link l,link r, int N){
	link x = (link)malloc(sizeof *x);
	x->item = item;x->l = l;x->r = r;x->N = N;
	if(head==z)head=x; //这句话不能少!!

。
	return x;
}
//初始化
void STinit(){
	head = ( z = NEW(NULLitem,0,0,0));
}

//右旋转 顺时针旋转
link rotR(link h){
	link x = h->l; h->l = x->r; x->r=h;
}
//左旋转 逆时针旋转
link rotL(link h){
	link x = h->r; h->r = x->l; x->l=h;
}

//根插入程序
link insertT(link h, Item item){
//	Key v = key(item), t = key(h->item);
	char v = item.c, t = h->item.c;
	if(h==z)return NEW(item,z,z,1);
	if(v<t) {h->l = insertT(h->l,item); h = rotR(h); }
	else {h->r = insertT(h->r,item); h = rotL(h);}
	(h->N)++;return h;
}

//随机化插入程序
link insertR(link h, Item item){
//	Key v = key(item), t = key(h->item);
	char v = item.c, t = h->item.c;
	if(h==z)return NEW(item,z,z,1);
	if(rand() < RAND_MAX / (h->N+1))
		return  insertR(h,item);  //使得新节点出如今树根的概率是1/(N+1)
	if(v<t) {h->l = insertR(h->l,item); h = rotR(h); }
	else {h->r = insertR(h->r,item); h = rotL(h);}
	(h->N)++;return h;
}

//伸展插入
link splay(link h, Item item) {
	char v = item.c, t = h->item.c;
	if(h==z)return NEW(item,z,z,1);
	if(v<t){
		if(hl==z)return NEW(item,z,h,h->N+1);
		if(v<hl->item.c){
			hll=splay(hll,item); h = rotR(h);
		}else{
			hlr = splay(hlr,item); hl = rotL(hl);
		}
		return rotR(h);
	}
	else {
		if(hr==z)return NEW(item,h,z,h->N+1);
		if(v>hr->item.c){
			hrr=splay(hrr,item); h = rotL(h);
		}else{
			hrl = splay(hrl,item); hr = rotR(hr);
		}
		return rotL(h);
	}
}

//BST插入主程序
void STinsert(Item item){  //新插入的节点都会当作根节点
	head =  splay(head,item);
}

void sortR(link h){
	if(h==z)return;
	printf("%c ",h->item.c);
	sortR(h->l);
	sortR(h->r);
}
//二叉搜索树排序
void STsort(link h){
	sortR(h);
}

void test(){
	struct Item item1 = {322,‘a‘};
	struct Item item2 = {23,‘s‘};
	struct Item item3 = {2,‘e‘};
	struct Item item4 = {332,‘r‘};
	struct Item item5 = {332,‘c‘};
	struct Item item6 = {332,‘h‘};
	struct Item item7 = {112,‘i‘};
	STinit();
	STinsert(item1);STinsert(item2);
	STinsert(item3);STinsert(item4);
	STinsert(item5);STinsert(item6);
	STinsert(item7);
	STsort(head);
}

main(){
	test();
}
时间: 2024-10-09 19:40:58

二叉搜索树的随机化插入和伸展插入操作(平摊法)的相关文章

链式二叉搜索树#插入节点#

定义一个二叉树节点的数据结构如下: typedef struct TREE_NODE { TREE_TYPE value; struct TREE_NODE *pLeft; struct TREE_NODE *pRight; }TreeNode; 插入节点的原型为:void insert(TreeNode **pLink,TREE_TYPE data): 如果要将数组元素a[10]={20,12,25,5,16,28,2,17,26,29}; 下面分两种情况讨论: ①    :当二叉搜索树为空时

Java数据结构之二叉搜索树

Java数据结构之二叉搜索树 1.二叉搜索树组成 二叉搜索树又称为二叉排序树,它或者是一颗空树,或者是一颗具有如下特性的非空二叉树,需要满足一下三个条件: (1)若它的左子树非空,则左子树上所有结点的关键字均小于根结点的关键字: (2)若它的右子树非空,则右子树上所有结点的关键字均大于(可以等于)根结点的关键字. (3)左子树右子树本身又各是一颗二叉搜索树 在算法描述中,均以结点值的比较来代表其关键字的比较,因为若结点的值为类类型时,该类必须实现系统提供的java.lang.comparable

二叉搜索树的建立

二叉搜索树最大特征是:左边子结点的值<当前结点的值,右边子结点的值>当前结点的值. 依照这个特征,可以使用递归和非递归两种方式建立一颗二叉搜索树. 下面是我的代码,分明列举了递归和非递归的建立方式.最初写的代码与正确版本大致相同,但程序总是运行不通过,debug后发现问题在于指针操作错误.自以为对c语言非常熟稔了,但还是犯下如此幼稚的错误,所以贴出这个错误,作为一个警示. 2014/5/24 ps:原来二叉搜索树最难的地方在于删除操作,所以补充一个删除操作.此外,还明白了书本介绍二叉搜索树的原

树, 二叉树, 二叉搜索树

转载:Vamei   出处:http://www.cnblogs.com/vamei 树的特征和定义 树(Tree)是元素的集合.我们先以比较直观的方式介绍树.下面的数据结构是一个树: 树有多个节点(node),用以储存元素.某些节点之间存在一定的关系,用连线表示,连线称为边(edge).边的上端节点称为父节点,下端称为子节点.树像是一个不断分叉的树根. 每个节点可以有多个子节点(children),而该节点是相应子节点的父节点(parent).比如说,3,5是6的子节点,6是3,5的父节点:1

【算法导论】二叉搜索树

什么是二叉搜索树 顾名思义,一棵二叉搜索树是以一棵二叉树来组织的.这样一棵树可以使用一个链表数据结构来表示,其中每个结点就是一个对象.除了key和卫星数据之外,每个结点还包含属性left.right和p,它们分别指向结点的左孩子.右孩子和双亲.如果某个孩子结点和父结点不存在,则相应属性的值为NIL.根结点是树中唯一父指针为NIL的结点. 二叉搜索树中的关键字总是以满足二叉搜索树性质的方式来存储: 设x是二叉搜索树中的一个结点.如果y是x左子树中的一个结点,那么 y.key <= x.key.如果

纸上谈兵: 树, 二叉树, 二叉搜索树

树的特征和定义 树(Tree)是元素的集合.我们先以比较直观的方式介绍树.下面的数据结构是一个树: 树有多个节点(node),用以储存元素.某些节点之间存在一定的关系,用连线表示,连线称为边(edge).边的上端节点称为父节点,下端称为子节点.树像是一个不断分叉的树根. 每个节点可以有多个子节点(children),而该节点是相应子节点的父节点(parent).比如说,3,5是6的子节点,6是3,5的父节点:1,8,7是3的子节点, 3是1,8,7的父节点.树有一个没有父节点的节点,称为根节点(

初探二叉搜索树

二叉搜索树 二叉搜索树很明显来自于一种思想:二分查找. 二叉搜索树 很明显: 二叉搜索树并不要求是一棵完全二叉树 则左子树上所有结点的值均小于它的根结点的值:右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树. 对于二叉搜索树而言,有以下典型的操作: 1 插入,删除 2 查找 3 遍历:深度优先遍历(包括前序,中序,后序三种方式),广度优先遍历 对于插入而言:是一个比较简单的过程.自己思考代码的实现. 删除操作比较麻烦,先不讲 而关于查找操作吗,和插入操作差别不大,不讲

[LeetCode] Convert Sorted List to Binary Search Tree 将有序链表转为二叉搜索树

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. 这道题是要求把有序链表转为二叉搜索树,和之前那道Convert Sorted Array to Binary Search Tree 将有序数组转为二叉搜索树思路完全一样,只不过是操作的数据类型有所差别,一个是数组,一个是链表.数组方便就方便在可以通过index直接访问任意一个元

LeetCode(109):有序链表转换二叉搜索树

Medium! 题目描述: 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定的有序链表: [-10, -3, 0, 5, 9], 一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树: 0 / -3 9 / / -10 5 解题思路: 这道题是要求把有序链表转为二叉搜索树,和之前那道Convert Sorted A