數據結構系列,二叉排序樹的結點刪除、重排

二叉排序樹

又稱二叉查找樹,它或者是一棵空樹,或者是具有下列性質的二叉樹:

  1. 若它的左子樹不爲空,則左子樹上所有結點的值均小於它的根結點的值。
  2. 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值。
  3. 它的左右子樹,也分別爲二叉排序樹。

構造一棵二叉排序樹的目的,不是爲了排序,而是爲了提高查找、插入刪除關鍵字的速度。

二叉樹的刪除,需要保證一點,不能因爲刪除了結點,而讓這棵樹變得不滿足二叉排序樹的特性,所以需要分幾種情況:

  1. 如果要刪除的結點是葉子結點,可直接刪除,對樹的其他結點沒有影響。
  2. 如果要刪除的結點,只有左孩子,或者只有右孩子,這個結點被刪除後,將它的左孩子,或者右孩子整個移動到刪除結點的位置。
  3. 如要刪除的結點既有左孩子,又有右孩子,這種情況要複雜一些:

首先,我們在其左孩子,右孩子兩棵樹中,找一個最接近這個結點值的數,用這個數替換要刪除的結點;

然後,在一棵二叉排序中,最接近某個結點值的數通常有兩個,一個比它大的,一個比它小的,也就是對二叉排序樹中序遍歷後,得到一個序列,最接近它的兩個數,剛好是這個數的前驅和後繼。

結點刪除的圖示;

二叉排序樹的結構定義,及代碼實現:

#ifndef DATA_STRUCTURE_BINARY_SORT_TREE_CLASS_H
#define DATA_STRUCTURE_BINARY_SORT_TREE_CLASS_H

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 //存儲空間初始分配量
#define MAX_TREE_SIZE 100 //二叉樹最大結點樹

typedef int Status; //表示函數結果的狀態碼
typedef int TreeElemType; //樹節點的數據類型,暫定int
typedef TreeElemType SqBiTree[MAX_TREE_SIZE]; //順序存儲結構數組

typedef struct BiTNode {
    int data;//結點的值
    struct BiTNode *lchild, *rchild;//左右孩子指針
}BiTNode, *BiTree;

TreeElemType Nil = 0; //表示空元素

Status Delete(BiTree *p);
#endif
#include "BinarySortTree.h"

#include "iostream"
#include "cstdlib"
#include "cmath"
using namespace std;

#define arrayLength(array) sizeof(array) / sizeof(array[0])
const int array[11] = {62, 88, 58, 47, 35, 73, 51, 99, 37, 93, 36};

/*
*二叉排序樹的查找,樹T中是否存在key
*指針f指向T的雙親,其初始值爲空
* 若查找成功,指針p返回指向該數據元素結點,放回true
*否則指針p指向查找路徑的最後一個結點,返回false
*/
Status SearchBST(BiTree T, int key, BiTree father, BiTree *p) {
	if(!T) {
		*p = father;
		return FALSE;
	} else if (key == T->data) {
		*p = T;
		return TRUE;
	} else if (key < T->data) {
		//在左子樹中繼續查找
		return SearchBST(T->lchild, key, T, p);
	} else {
		//在右子樹中繼續查找
		return SearchBST(T->rchild, key, T, p);
	}
}

/*
*二叉排序樹的插入,當樹T中不存在key,插入key返回true,否則返回false
*因爲二叉樹會被修改,所以這裏用了指針
*/
Status InsertBST(BiTree *T, int key) {
	//BiTree是一個指針,所以p,s都是指針變量
	BiTree p, s;
	if (!(SearchBST(*T, key, NULL, &p))) {
		s = new BiTNode;
		s->data = key;
		s->lchild = s->rchild = NULL;
		//根據查找函數,如果p爲空,意味着這是一棵空樹,執行第一次插入
		if (!p) {
			*T = s;//s爲根結點
		} else if (key < p->data) {
			p->lchild = s;//s爲左孩子
		} else {
			p->rchild = s;//s爲右孩子
		}
		return TRUE;
	} else {
		return FALSE;//已存在指定結點,不再插入
	}
}

/*
* 這裏的參數,是一個指針常量,不能通過這個指針常量修改指針指向的常量的內容,
* 但是指針的指向是可以改變的,就是說這個指針常量還可以指向別的地方。
*/
Status CreateBST(BiTree *T, const int *p, int lenth) {
	int i;
	for (i = 0; i< lenth; p++, i++) {
		cout << "lenth=" << lenth << ",,,i="<<i <<",v= " << *p <<endl;
		InsertBST(T, *p);
	}
	return OK;
}

Status visit(BiTree T) {
	if (NULL != T) {
		cout << "value=" << T->data << endl;
	} else {
		cout << "T is null!" <<endl;
	}
	return OK;
}

void InOrderTraverseBST(BiTree T) {
	if (NULL == T) {
		//cout << "T is null!" <<endl;
		return;
	} else {
		InOrderTraverseBST(T->lchild);
		visit(T);
		InOrderTraverseBST(T->rchild);
	}
}

/*
* 二叉排序樹的刪除
* 若二叉排序中存在結點值等於key的數據元素,則刪除該結點,並返回TRUE,否則返回FLASE
*/
Status DeleteBST(BiTree *T, int key) {
	if (!*T) {//空樹
		return FALSE;
	} else {
		//找到了結點值等於key的數據元素
		if (key == (*T)->data) {
			return Delete(T);
		} else if (key < (*T)->data) {
			return DeleteBST(&((*T)->lchild), key);
		} else {
			return DeleteBST(&((*T)->rchild), key);
		}
	}
}

/*
*刪除結點,重排它的左右子樹
*/
Status Delete(BiTree *p) {
	BiTree q, s;
	if (NULL == (*p)->rchild) {
		//只有左孩子,就用它的左孩子替換要刪除的結點
		q = *p;
		*p = (*p)->lchild;
		delete q;
	} else if (NULL == (*p)->rchild) {
		//只有右孩子,就用它的右孩子替換要刪除的結點
		q = *p;
		*p = (*p)->rchild;
		delete q;		
	} else {
		//1,q指向要刪除的結點,s指向要刪除結點的左孩子。
		q = *p;
		s = (*p)->lchild;
		//2,在左孩子中找最大值,也就是找刪除點的前驅
		while (s->rchild) {
			q = s;
			s = s->rchild;
		}
		//3,用s替換被刪除的結點
		(*p)->data = s->data;
		if (q != *p) {
			//重置q的右子樹
			q->rchild = s->lchild;
		} else {
			//重置q的左子樹
			q->lchild = s->lchild;
		}
		delete s;
	}

	return TRUE;
}

int main() {
	BiTree T = NULL;
	CreateBST(&T, array, arrayLength(array));
	InOrderTraverseBST(T);
	int deleteNode = 47;
	DeleteBST(&T, deleteNode);
	cout << "after delete the node :" << deleteNode << endl;
	InOrderTraverseBST(T);
}

/*output*/

g++ -g BinarySortTree.cpp -o BsTree
./BsTree

lenth=11,,,i=0,v= 62
lenth=11,,,i=1,v= 88
lenth=11,,,i=2,v= 58
lenth=11,,,i=3,v= 47
lenth=11,,,i=4,v= 35
lenth=11,,,i=5,v= 73
lenth=11,,,i=6,v= 51
lenth=11,,,i=7,v= 99
lenth=11,,,i=8,v= 37
lenth=11,,,i=9,v= 93
lenth=11,,,i=10,v= 36
value=35
value=36
value=37
value=47
value=51
value=58
value=62
value=73
value=88
value=93
value=99
after delete the node :47
value=35
value=36
value=37
value=51
value=58
value=62
value=73
value=88
value=93
value=99

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章