1. 程式人生 > >STL原始碼—二叉樹查詢樹

STL原始碼—二叉樹查詢樹

為了進一步瞭解RB樹,先了解一下二叉查詢樹

定義:

二叉查詢樹是一棵二叉樹,因此可以用鏈式結構來儲存資料。若二叉查詢樹不為空,則應具有以下性質:

  1. 關鍵字的值唯一
  2. 若左子樹不為空,則子樹任何節點關鍵字值一定小於其根節點的關鍵字值
  3. 若右子樹不為空,則子樹任何節點關鍵字值一定大於其根節點的關鍵字值
  4. 左、右子樹任然是二叉查詢樹
結構示意圖

查詢節點:

  1. 若二叉查詢樹為空,則查詢失敗
  2. 若該樹非空且查詢資料x等於根節點的值,則查詢成功,返回根節點
  3. 若該樹非空且查詢資料x小於根節點的值,則查詢左子樹,直到值相等,並返回節點
  4. 若該樹非空且查詢資料x大於根節點的值,則查詢右子樹,直到值相等,並返回節點

插入節點:

  1. 若二叉查詢樹為空,則將結點作為根節點插入
  2. 若所插入節點關鍵字值等於根節點的值,則插入失敗,並返回
  3. 若所插入節點關鍵字值小於根節點的值,則把節點插入到左子樹中
  4. 若所插入節點關鍵字值大於根節點的值,則把節點插入到右子樹中

刪除節點:

  1. 若p結點為葉子結點,則刪去該葉子結點,修改其雙親結點的指標即可。
  2. 若p結點只有左子樹PL或右子樹PR,此時只要令PL或PR直接成為其雙親結點的左子樹(當p是左子樹)或右子樹(當p是右子樹)。
  3. 若p結點的左子樹和右子樹均不空。找出節點p的後繼節點y(一定在節點p的右子樹中),以右子樹中的最小數作為後繼節點。
下面是實現這些功能的程式
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

#define LENGTH 11

struct BinSearNode
{
	int key;
	struct BinSearNode *left_child;
	struct BinSearNode *right_child;
	struct BinSearNode *parent;
}Node;
typedef struct BinSearNode *PNode;

/*Search the node of the tree*/
PNode Search_Tree(PNode root,int key)
{
	PNode x=root;
	//the tree is not empty and the key is not equal
	while(NULL!=x && x->key!=key)
	{
		if(x->key<key)
			x=x->right_child;//along the right child of tree,until it is empty
		else
			x=x->left_child;//along the left child of tree,until it is empty
	}
	return x;//return the node
}
/*the minimum key of node in the tree*/
PNode Minimum_Tree(PNode root)
{
	PNode x=root;
	while(NULL!=x->left_child)
	{
		x=x->left_child;
	}
	return x;
}
/*the maxmum key of node in the tree*/
PNode Maxmum_Tree(PNode root)
{
	PNode x=root;
	while(NULL!=x->right_child)
	{
		x=x->right_child;
	}
	return x;
}
/*the successor node of the x,後繼節點可以這麼理解,將查詢樹從小到大排序,比他大的值
如果有右孩子,那麼應該是右子樹當中的最小值
如果沒有右孩子,那麼應該向上追溯,直至一個分支節點是其父節點的左孩子,返回父節點
可以用於operate++*/
PNode Successor_Tree(PNode x)
{
	PNode y=NULL;
	//case 1:the right subtree of node x is not empty
	if(NULL!=x->right_child)
	{
		y=Minimum_Tree(x->right_child);
	}
	//case 2:the right subtree of node x is empty
	//and the node of x has a successor node y
	else
	{
		y=x->parent;
		while(NULL!=y && x==y->right_child) 
		{
			x=y;
			y=y->parent;
		}
	}
	return y;
}
/*the predecessor node of the x,前任節點
如果節點有左孩子,那麼找到左孩子的最大值
如果沒有左孩子,那麼向上追溯直至一個分支當前節點是對應父節點的右孩子,返回父節點的值
*/
PNode Predecessor_Tree(PNode x)
{
	PNode y=NULL;
	//case 1:the left subtree of node x is not empty
	if(NULL!=x->left_child)
	{
		y=Maxmum_Tree(x->left_child);
	}
	//case 2:the left subtree of node x is empty
	//and the node of x has a predecessor node y
	else
	{
		y=x->parent;
		while(NULL!=y && x==y->left_child)
		{
			x=y;
			y=y->parent;
		}
	}
	return y;
}

/*insert a new node into the BST*/
void Insert_Tree(PNode *root,int key)
{
	PNode x=*root;
	PNode y=NULL;
	PNode z=(PNode)malloc(sizeof(Node));//<開闢一個節點的空間
	if(NULL==z)
	{
		printf("malloc the z is failed.");
		exit(1);
	}
	//initial the node of z
	z->key=key;
	z->left_child=z->right_child=z->parent=NULL;
	//Find the location node of y to insert the node of z
	while(NULL!=x)
	{
		y=x; //<找到當前樹滿足條件的葉子節點了,表示為y,之後在y節點後面進行插入操作
		if(z->key<x->key)
			x=x->left_child;
		else
			x=x->right_child;
	}
	//insert the node of z
	z->parent=y;
	if(NULL==y)
		*root=z;//tree was empty
	else
	{
		if(z->key<y->key)
			y->left_child=z;
		else
			y->right_child=z;
	}
}
void Transplant(PNode *root,PNode u,PNode v)
{
	if(NULL==u->parent)
		*root=v;
	else
	{
		if(u==u->parent->left_child)
			u->parent->left_child=v;
		else
			u->parent->right_child=v;
	}
	if(NULL!=v)
		v->parent=u->parent;
}
/*delete a node in the binary search tree*/
void Delete_Tree(PNode *root,int key) //<刪除節點
{
	//Find the node you want to delete
	PNode p=Search_Tree(*root,key);
	if(NULL==p->left_child)
		Transplant(root,p,p->right_child);
	else
	{
		if(NULL==p->right_child)
			Transplant(root,p,p->left_child);
		else
		{
			PNode y=Successor_Tree(*root);
			if(y->parent!=p)
			{
				Transplant(root,y,y->right_child);
				y->right_child=p->right_child;
				y->right_child->parent=y;
			}
			Transplant(root,p,y);
			y->left_child=p->left_child;
			y->left_child->parent=y;
		}
	}
}
/*print the key of binary search tree*/
void ioder_Tree(PNode root)
{
	if(NULL!=root)
	{
		ioder_Tree(root->left_child);
		printf("  %d",root->key);
		ioder_Tree(root->right_child);
	}
}
int main()  
{  
	int i;  
	int Arr[LENGTH]={16,6,20,2,7,19,22,1,4,11,8};  
	PNode root=NULL;  
	PNode p=NULL;  
	for(i=0;i<LENGTH;i++)  
	{  
		Insert_Tree(&root,Arr[i]);  
	}  
	ioder_Tree(root);  
	printf("\n");  
	//printf("Hello world!\n");  
	Delete_Tree(&root,11);  
	ioder_Tree(root);  
	printf("\n");  
	p=Maxmum_Tree(root);  
	printf("The Maxmum of node is:%d\n",p->key);  
	p=Minimum_Tree(root);  
	printf("The Minimum of node is:%d\n",p->key);  
	return 0;  
}  

結果圖:


在STL中除了要求是搜尋二叉樹之外,還需要是平衡搜尋二叉樹:

因為關聯容器很重要的一個是搜尋效率

平衡樹有很多種比如AVL_tree,RB-tree,AA-tree

平衡二叉樹插入節點和刪除節點的平均時間都是比較長,但是他們可以很好的避免難以應付的最壞情況

AVL-tree要求任何節點的左右子樹的高度相差最多為1

如果插入或者刪除操作打破了這些平衡條件,那麼這樣的樹應該需要做相應的旋轉操作來達到平衡

RB-tree的節點有紅色和黑色的區分,並有一些限制條件,之後會專門進行介紹


相關推薦

STL原始碼查詢

為了進一步瞭解RB樹,先了解一下二叉查詢樹 定義: 二叉查詢樹是一棵二叉樹,因此可以用鏈式結構來儲存資料。若二叉查詢樹不為空,則應具有以下性質: 關鍵字的值唯一若左子樹不為空,則子樹任何節點關鍵字值一定小於其根節點的關鍵字值若右子樹不為空,則子樹任何節點關鍵字值一定

排序(查詢)的實現

二叉樹排序樹又稱二叉查詢數。它或者是一棵空數,或者是具有下列性質的二叉樹: ①如果左子樹不為空,那麼左子樹上所有節點的值均小於它的根節點的值; ②如果右子樹不為空,那麼右子樹上所有節點的值均大於其根節點的值; ③左右子樹也分別為二叉排序樹 實現方法: package

poj2418 Hardwood Species STL熟悉+查詢

Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nut, and generally go dormant in the w

STL實現遍歷

nod 數據 blog new friend const turn ace lrn #include<iostream> using namespace std; template<class Type> class BSTree; templat

簡單實現搜尋 (查詢)

直接看程式碼 /** * @author <a href=mailto:[email protected]>maple</a> * @since 2018-11-25 11:40 PM */ // 二分搜尋樹 // 由於Key需要能夠進行比較,所以需要extends

用python實現搜尋/查詢的簡單實現及驗證(判斷)(三)(棧中根序遍歷)

基於棧的中根序深度優先遍歷判斷法(天然排序,每次比上一個值大即可)。由搜尋樹的性質推得中根序深度遍歷為一個從小到大的有序序列。所以根據這一性質事情就好辦了,只要在遍歷過程中加入與前一值得比較判斷即能達到目的(複雜度O(n),推薦演算法)。程式碼如下:def midorder(

BST搜尋(查詢)實現 程式碼+詳解(C/C++)

寫了一下午,終於把這個整理完了,也相當於複習了一波資料結構吧。。。   概念 二叉查詢樹(Binary Search Tree),又被稱為二叉搜尋樹,二叉排序樹。 為什麼叫二叉查詢樹呢,因為它一般的樹不同,它具有如下性質 若它的左子樹不空,則左子樹上所有結點的

手寫排序(查詢、搜尋)

二叉排序樹(查詢樹,搜尋樹)或者是一顆空樹,或者是一顆具有如下性質的樹: 1)若左子樹不為空,那麼左子樹上面的所有節點的關鍵字值都比根節點的關鍵字值小 2)若右子樹不為空,那麼右子樹上面的所有節點的關鍵字值都比根節點的關鍵字值大 3)左右子樹都為二叉樹 4)沒有重複值(這一點在實際中可以忽略)

STL搜尋(set)

《挑戰程式設計競賽》,初級篇–樹 // set初步使用 #include <cstdio> #include <set> using namespace std; int main() { set<int> s

STL搜尋(map)

《挑戰程式設計競賽》,初級篇–樹 // map初步使用 #include <cstdio> #include <cstring> #include <map> using namespace std; int main

c++排排序的實現 補上了刪除和查詢操作

#include <iostream> #include<stack> using namespace std; class node{     friend class tree; public:     node* left;     int d

搜索(模板)

int ret class get name cnblogs clu space tin #include<cstdio> using namespace std; const int M=9999; struct tr{ int l,r,x,size,nu

題目1009:搜索(搜索的建立)

nor style https 題目 .com tree ont cnblogs char 題目鏈接:http://ac.jobdu.com/problem.php?pid=1009 詳解鏈接:https://github.com/zpfbuaa/JobduInCPlus

查找python實現

treenode pri one val name turn 是否 find pan 1. 二叉查找樹的定義: 左子樹不為空的時候。左子樹的結點值小於根節點,右子樹不為空時,右子樹的結點值大於根節點。左右子樹分別為二叉查找樹 2. 二叉查找樹的最左邊的結點即為最小值,要

給定有序數組,創建高度最小的查找

enter reat 技術 二叉查找樹 treenode ret new t pre 有序數組 TreeNode createMinimalBST(int arr[], int start, int end) { if (end < start) { r

搜索的隨機化插入和伸展插入操作(平攤法)

新節點 div fine mod and sta std splay ins 源碼例如以下: #include <stdlib.h> #include <stdio.h> //#define Key int #define hl h->l

九度OJ-題目1009:搜索

提交 二叉排序樹 軟件 amp cpp creat .com xheditor ear 題目1009:二叉搜索樹 從如今開始打算重新啟動刷題征程。程序猿的人生不須要解釋! 這次撇開poj hoj等難度較大的oj系統,從九度入手(已經非常長時間沒寫過代碼

AVL(平衡查找

出現 尋找 findmi 有意 出了 操作 amp 為什麽 9.png 首先要說AVL樹,我們就必須先說二叉查找樹,先介紹二叉查找樹的一些特性,然後我們再來說平衡樹的一些特性,結合這些特性,然後來介紹AVL樹。 一、二叉查找樹 1、二叉樹查找樹的相關特征定義 二叉樹查找樹,

LeetCode96_Unique Binary Search Trees(求1到n這些節點能夠組成多少種不同的查找) Java題解

binary == -1 value -a 不同 truct ota -h 題目: Given n, how many structurally unique BST‘s (binary search trees) that store values 1...n?

數據結構與算法問題 搜索

它的 ng- type i++ 刪掉 簡單 font 數據結構與算法 -a 1、序 具體實現了二叉查找樹的各種操作:插入結點、構造二叉樹、刪除結點、查找、 查找最大值、查找最小值、查找指定結點的前驅和後繼 2、二叉查找樹簡單介紹 它或者是一棵空樹;