1. 程式人生 > >BST二叉排序樹的查詢和刪除的完整C程式碼

BST二叉排序樹的查詢和刪除的完整C程式碼

二叉排序樹的查詢演算法

假定二叉排序樹的根節點指標為root,給定的關鍵字值為key,則查詢演算法可描述為:

  1. 置初值:p = root ;

  2. 如果 key = p -> data ,則查詢成功,演算法結束;

  3. 否則,如果key < p->data ,而且 p 的左子樹非空,則將 p 的左子樹根送 p ,轉步驟 2 ;否則,查詢失敗,演算法結束;

  4. 否則,如果 key > p->data ,而且 p 的右子樹非空,則將 p 的右子樹根送 p ,轉步驟 2 ;否則,查詢失敗,演算法結束。

//BST的遞迴查詢
void SearchBST( BiTree t, Elemtype key )
{
	BiTree p;
	p = t;
	if( p ) {
		if( key == p->data )
			printf("查詢成功!\n");
		else if( (key < p->data) && (NULL != p->lchild) )
			SearchBST( p->lchild , key );
		else if( (key > p->data) && (NULL != p->rchild) )
			SearchBST( p->rchild , key );
		else
			printf("無此元素!\n");
	}
}

//BST的迭代查詢
void _SearchBST( BiTree t, Elemtype key )
{
	BiTree p;
	p = t;
	while( NULL != p && key != p->data ) {
		if( key < p->data )
			p = p->lchild ;
		else
			p = p->rchild ;
	}

	if( NULL != p )
		printf("查詢成功!\n");
	else
		printf("無此元素!\n");
}

二叉排序樹上結點的刪除演算法

假設要刪除的結點為 p ,結點 p 的雙親結點為 q ,下面分三種情況討論:

  1. 若 p 為葉子結點,則可直接將其刪除:
    //情況1:結點p的雙親結點為q,且p為葉子結點,則直接將其刪除。
    		if( NULL == p->lchild && NULL == p->rchild ) {
    			if( p == q->lchild )
    				q->lchild = NULL;
    			if( p == q->rchild )
    				q->rchild = NULL;
    			free(p);
    			p = NULL;
    		}


  2. 若 p 結點只有左子樹,或只有右子樹,則可將 p 的左子樹或右子樹直接改為其雙親結點 q 的左子樹或右子樹:
    //情況2:結點p的雙親結點為q,且p只有左子樹或只有右子樹,則可將p的左子樹或右子樹直接改為其雙親結點q的左子樹或右子樹。
    		else if( (NULL == p->rchild && NULL != p->lchild) ) {	//p只有左子樹
    			if( p == q->lchild )
    				q->lchild = p->lchild ;
    			else if( p == q->rchild )
    				q->rchild = p->lchild ;
    			free(p);
    			p = NULL;
    		}
    		else if( NULL == p->lchild && NULL != p->rchild ) {	//p只有右子樹
    			if( p == q->lchild )
    				q->lchild = p->rchild ;
    			if( p == q->rchild )
    				q->rchild = p->rchild ;
    			free(p);
    			p = NULL;
    		}


  3. 若 p 既有左子樹,又有右子樹。則先儲存p 結點的直接前驅(或直接後繼)s 的 data  ,然後再從二叉排序樹中刪除 s ,最後將儲存起來的 s 結點的 data 賦值給 p 的 data 。

    該步驟難點在於準確理解 p 結點的直接前驅或直接後繼的概念。

    這裡的 p 的直接前驅是指BST的中序遍歷序列中,緊挨在 p 結點之前一個的結點 s ,在BST中,s 位於 p 結點的左子樹的最右下方,用 s 的資料代替 p 的資料,該二叉樹依然是一個二叉排序樹。
    同理,p 的直接後繼是指BST的中序遍歷序列中,緊挨在 p 結點之後一個的結點 s , 在BST中, s 位於 p 結點的右子樹的最左下方,用 s 的資料代替 p 的資料,該二叉樹依然是一個二叉排序樹。

    //情況3:結點p的雙親結點為q,且p既有左子樹又有右子樹。本程式碼使用直接前驅(也可以直接後繼)
    	
    		else if( NULL != p->lchild && NULL != p->rchild ) {
    				BiTree s, sParent; 
    				sParent = p;
    				s = sParent->lchild ;
    				while( NULL != s->rchild )	{	//找到p的直接前驅
    					sParent = s;
    					s = s->rchild ;	
    				}
    				temp = s->data ;	
    				DelBSTNode( t, temp );
    				p->data = temp;
    		}

BST查詢和刪除結點的完整C程式碼

/* 二叉排序樹的查詢演算法的C程式碼實現 */
#include <stdio.h>
#include <stdlib.h>

typedef int Elemtype;

typedef struct BiTNode{
	Elemtype data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//在給定的BST中插入結點,其資料域為element
void BSTInsert( BiTree *t, Elemtype element )
{
	if( NULL == *t ) {
		(*t) = (BiTree)malloc(sizeof(BiTNode));
		(*t)->data = element;
		(*t)->lchild = (*t)->rchild = NULL;
	}

	if( element == (*t)->data )
		return ;

	else if( element < (*t)->data )
		BSTInsert( &(*t)->lchild, element );

	else 
		BSTInsert( &(*t)->rchild, element );
}

//建立BST
void CreateBST( BiTree *t, Elemtype *a, int n )
{
	(*t) = NULL;
	for( int i=0; i<n; i++ )
		BSTInsert( t, a[i] );
}

//BST的遞迴查詢
void SearchBST( BiTree t, Elemtype key )
{
	BiTree p;
	p = t;
	if( p ) {
		if( key == p->data )
			printf("查詢成功!\n");
		else if( (key < p->data) && (NULL != p->lchild) )
			SearchBST( p->lchild , key );
		else if( (key > p->data) && (NULL != p->rchild) )
			SearchBST( p->rchild , key );
		else
			printf("無此元素!\n");
	}
}

//BST的迭代查詢
void _SearchBST( BiTree t, Elemtype key )
{
	BiTree p;
	p = t;
	while( NULL != p && key != p->data ) {
		if( key < p->data )
			p = p->lchild ;
		else
			p = p->rchild ;
	}

	if( NULL != p )
		printf("查詢成功!\n");
	else
		printf("無此元素!\n");
}

//BST結點的刪除
void DelBSTNode( BiTree t, Elemtype key )
{
	BiTree p, q;
	p = t;
	Elemtype temp;
	while( NULL != p && key != p->data ) {
		q = p;
		if( key < p->data )
			p = p->lchild ;
		else
			p = p->rchild ;
	}

	if( NULL == p )
		printf("無此元素!\n");
	else {
		//情況1:結點p的雙親結點為q,且p為葉子結點,則直接將其刪除。
		if( NULL == p->lchild && NULL == p->rchild ) {
			if( p == q->lchild )
				q->lchild = NULL;
			if( p == q->rchild )
				q->rchild = NULL;
			free(p);
			p = NULL;
		}
		//情況2:結點p的雙親結點為q,且p只有左子樹或只有右子樹,則可將p的左子樹或右子樹直接改為其雙親結點q的左子樹或右子樹。
		else if( (NULL == p->rchild && NULL != p->lchild) ) {	//p只有左子樹
			if( p == q->lchild )
				q->lchild = p->lchild ;
			else if( p == q->rchild )
				q->rchild = p->lchild ;
			free(p);
			p = NULL;
		}
		else if( NULL == p->lchild && NULL != p->rchild ) {		//p只有右子樹
			if( p == q->lchild )
				q->lchild = p->rchild ;
			if( p == q->rchild )
				q->rchild = p->rchild ;
			free(p);
			p = NULL;
		}
		//情況3:結點p的雙親結點為q,且p既有左子樹又有右子樹。本程式碼使用直接前驅(也可以直接後繼)
	
		else if( NULL != p->lchild && NULL != p->rchild ) {
				BiTree s, sParent; 
				sParent = p;
				s = sParent->lchild ;
				while( NULL != s->rchild )	{	//找到p的直接前驅
					sParent = s;
					s = s->rchild ;	
				}
				temp = s->data ;	
				DelBSTNode( t, temp );
				p->data = temp;
		}
	}

}

//中序遍歷列印BST
void PrintBST( BiTree t )
{
	if( t ) {
		PrintBST( t->lchild );
		printf("%d ", t->data);
		PrintBST( t->rchild );
	}
}

int main()
{
	int n;
	int *a;
	Elemtype key;
	BiTree t;

	printf("請輸入二叉查詢樹的結點數:\n");
	scanf("%d", &n);

	a = (int *)malloc(sizeof(int)*n);
	printf("請輸入二叉找樹的結點資料:\n");
	for( int i=0; i<n; i++ )
		scanf("%d", &a[i]);
	CreateBST( &t, a, n );
	printf("當前二叉查詢樹的中序遍歷結果為:\n");
	PrintBST( t );
	printf("\n##############################################\n");
	
	printf("請輸入要查詢的元素:\n");
	scanf("%d", &key);
	printf("BST遞迴查詢結果:\n");
	SearchBST( t, key );		//遞迴查詢

	printf("##############################################\n");
	printf("請輸入要刪除的元素:\n");
	scanf("%d", &key);
	DelBSTNode( t, key );
	printf("當前二叉查詢樹的中序遍歷結果為:\n");
	PrintBST( t );
	printf("\n##############################################\n");

	printf("請輸入要查詢的元素:\n");
	scanf("%d", &key);
	printf("BST迭代查詢結果:\n");
	_SearchBST( t, key );		//迭代查詢

	return 0;
}

測試資料以及測試結果

9個元素:5 8 2 1 4 7 9 6 3

生成的BST:

測試結果:

測試通過。

相關推薦

BST排序查詢刪除完整C程式碼

二叉排序樹的查詢演算法 假定二叉排序樹的根節點指標為root,給定的關鍵字值為key,則查詢演算法可描述為: 置初值:p = root ;如果 key = p -> data ,則查詢成功,演算法結束;否則,如果key < p->data ,而且 p 的

索引順序表查詢排序查詢

二叉排序樹(BST)的定義為:二叉排序樹或者是空樹,或者是滿足下列性質的二叉樹: (1) :若左子樹不為空,則左子樹上所有結點的值(關鍵字)都小於根結點的值; (2) :若右子樹不為空,則右子樹上所有結點的值(關鍵字)都大於根結點的值; (3) :左、右子樹都分別是二叉

C++實現排序BSTree --插入刪除摧毀查詢等操作

#ifndef _BSTREE_H #define _BSTREE_H #include <iostream> #include <assert.h> using namespace std; template <typename T> class BSTree; t

程式設計基礎79 給定排序結構陣列求整棵

1099 Build A Binary Search Tree (30 分) A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: T

排序查詢演算法之php實現

        二叉排序樹,又稱為二叉查詢樹。它或者是一棵空樹,或者是具有下列性質的二叉樹。                1.若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值                2.若它的右子樹不空,則右子樹上所有結點的值均小於它

排序查詢效率最高的是哪個?

1.平衡二叉樹:它是一棵空樹或者它的左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。 如上圖:平衡二叉樹 2.二叉查詢樹:二叉排序樹,又稱二叉查詢樹,或者稱為二叉搜尋樹。

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

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

手寫排序(查詢、搜尋)

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

查詢-排序查詢

二叉排序樹的性質: (1)若某節點的左子樹非空,則左子樹上所有元素的值都小於該元素的值。 (2)若某節點的右子樹非空,則右子樹上所有元素的值都大於該元素的值。 問題:在二叉排序樹種,原則上各元素關

排序的結點刪除

8 3 9 2 6 10 1 4 7 5 上面是1到10的二叉排序樹。 如何實現二叉排序樹的節點刪除呢?假設我們刪除結點6,先尋找前驅結點或者後繼節點,6的前驅結點是5,後繼是7,想象一下

資料結構 折半遞迴查詢排序查詢

實驗題目:         查詢演算法實現與分析              實驗環境:     Visual C++ 6.0                     實驗專案七:查詢演算法實現與分析  實驗目的:1.掌握順序表的查詢方法,尤其是二分查詢方法。       

查詢排序(Binary Sort Tree)及其C實現

大話資料結構學習筆記 - 查詢之二叉排序樹(Binary Sort Tree)及其C實現 二叉排序樹 二叉排序樹(Binary Sort Tree):又稱為 二叉查詢樹, 它或者是一個空樹,或者是具有下列性質的二叉樹 若它的左子樹不空,則左子樹上

java實現順序查詢、二分查詢、雜湊表查詢排序查詢

順序查詢、二分查詢、雜湊表查詢、二叉排序樹查詢這幾種查詢演算法是面試中常被問到的幾種演算法。 1. 順序查詢     對於陣列,按順序比較給定的值,時間複雜度0(n),,以下是實現: public static int Linear_Search(int[] data, i

排序基本功能實現(C++)

二叉排序樹(Binary Sort Tree )也稱二叉搜尋樹(Binary Search Tree),以下簡稱BST。 它的特點是左小右大(左子樹小於根,右子樹大於根),令人困惑的是他不允許相等存在,一定要分個高低。這個特點與二叉堆排序有所不同,堆是允許存在相同關鍵字

排序的操作(建立、插入、刪除查詢

二叉排序樹的建立、插入、刪除和查詢 #include <stdio.h> #include <stdlib.h> typedef struct node { int key; struct node *lchild,*rchild

【資料結構表的查詢排序詳解程式碼(生成、插入、查詢、最大值、最小值、刪除、中序遍歷、銷燬)

二叉排序樹(簡稱BST)又稱二叉查詢(搜尋)樹,其定義為:二叉排序樹或者是空樹,或者是滿足如下性質的二叉樹:       (1)若它的左子樹非空,則左子樹上所有記錄的值均小於根記錄的值;       (2)若它的右子樹非空,則右子樹上所有記錄的值均大於根記錄的值;     

查詢(3)——排序的建立、結點的查詢刪除

#include <stdio.h> #include <stdlib.h> typedef struct node{ int data; node * lchild; node * rchild; }BTree

排序(查詢)BST構造,節點插入,節點查詢,節點刪除(java)

二叉排序樹(BST)的構造,節點插入,節點查詢,節點刪除(java) 高度最小BST(同樣資料,順序可能不一樣) package ccnu.offer.tree; import java.util.ArrayList; import java.ut

BST排序)的插入與刪除

最小值 temp def oot gpo 一個 記錄 通過 如果 值得一說的是刪除操作,刪除操作我們分為三種情況: 1.要刪的節點有兩個孩子:   找到左子樹中的最大值或者右子樹中的最小值所對應的節點,記為node,並把node的值賦給要刪除的節點del,然後刪除node

【模板】搜尋排序查詢BST

二叉搜尋樹其實就是滿足左結點小於根,右結點大於根這類規則的樹形結構。  1 int n; 2 int a[MAX_N]; 3 int lt[MAX_N], rt[MAX_N]; 4 // 沒有則為-1 5 // 預設a[0]為根結點 6 7 void Insert(int