二叉排序樹詳解

       二叉排序樹(Binary Sort Tree或Binary Search Tree) 的定義爲:二叉排序樹或者是空樹,或者是滿足下列性質的二叉樹。
(1) :若左子樹不爲空,則左子樹上所有結點的值(關鍵字)都小於根結點的值;
(2) :若右子樹不爲空,則右子樹上所有結點的值(關鍵字)都大於根結點的值;
(3) :左、右子樹都分別是二叉排序樹。
       結論:若按中序遍歷一棵二叉排序樹,所得到的結點序列是一個遞增序列。
                   BST仍然可以用二叉鏈表來存儲
節點結構定義如下:
struct BiTNode 
{
	int data;
	struct BiTNode *lchild,*rchild;
};
typedef struct BiTNode BiTNode,*biTree;

一、二叉排序樹的查找
      
1  查找思想
      首先將給定的K值與二叉排序樹的根結點的關鍵字進行比較:若相等:則查找成功;
①給定的K值小於BST的根結點的關鍵字:繼續在該結點的左子樹上進行查找;
②   給定的K值大於BST的根結點的關鍵字:繼續在該結點的右子樹上進行查找。
2 代碼實現
biTree SearchBST(biTree T,int key)
{
	//在根指針T所指的二叉排序樹中遞歸地查找某關鍵字等於key的數據元素
	//若查找成功,則返回指向數據元素節點的指針,否則,返回空指針
	if (T==NULL)
	{
		return NULL;
	}
	else
	{
		if (key==T->data)
		{
			return T;
		}
		else if (key<T->data)
		{
			return (SearchBST(T->lchild,key));
		}
		else
		{
			return(SearchBST(T->rchild,key));
		}
	}

}



二、插入
1,插入思想
在BST樹中插入一個新結點x時,若BST樹爲空,則令新結點x爲插入後BST樹的根結點;否則,將結點x的關鍵字與根結點T的關鍵字進行比較:
①若相等:不需要插入;
②  若x.key<T->key:結點x插入到T的左子樹中;
③  若x.key>T->key:結點x插入到T的右子樹中
2,代碼實現
void  InsertBST (biTree &T , int key)
{	

	
	if (T==NULL)
	{
		biTree x;
		x=new BiTNode;
		x->data=key;
		x->lchild=x->rchild=NULL;
		T=x;
		cout<<"插入成功\n";
	}
	else
	{
		if (T->data==key)
		{
			cout<<"節點已存在\n"<<endl;
		}
		else if (key<T->data)
		{
			InsertBST(T->lchild,key);
		}
		else
		{		
			InsertBST(T->rchild,key);
		}
	}
	
}


三、刪除
1,刪除思想
從BST樹上刪除一個結點,仍然要保證刪除後滿足BST的性質。設被刪除結點爲p,其父結點爲f ,刪除情況如下:
①  若p是葉子結點:直接刪除p,如圖9-5(b)所示。
②  若p只有一棵子樹(左子樹或右子樹):直接用p的左子樹(或右子樹)取代p的位置而成爲f的一棵子樹。即原來p是f的左子樹,則p的子樹成爲f的左子樹;原來p是f的右子樹,則p的子樹成爲f的右子樹
若p既有左子樹又有右子樹:處理方法有以下兩種,可以任選其中一種。
◆  用p的直接前驅結點代替p。即從p的左子樹中選擇值最大的結點s放在p的位置(用結點s的內容替換結點p內容),然後刪除結點s。s是p的左子樹中的最右邊的結點且沒有右子樹,對s的刪除同②,如圖9-5(e)所示。
用p的直接後繼結點代替p。即從p的右子樹中選擇值最小的結點s放在p的位置(用結點s的內容替換結點p內容),然後刪除結點s。s是p的右子樹中的最左邊的結點且沒有左子樹,對s的刪除同②

2,代碼實現
int dele(biTree &p)
{
	biTree q,s;
	if (p->lchild==NULL)
	{
		q=p;
		p=p->lchild;
		delete q;
	}
	else if (p->rchild==NULL)
	{
		q=p;
		p=p->rchild;
		delete q;
	}
	else
	{
		q=p;
		s=p->lchild;
		while(s->rchild)
		{
			q=s;
			s=s->rchild;
		}
		p->data=s->data;
		if (q!=p)
		{
			q->rchild=s->lchild;
		}
		else
		{
			q->lchild=s->lchild;
		}
		delete s;

	}
	return 1;
	
}
int deleteBTree(biTree &T,int num)
{
	if (T==NULL)
	{
		return 0;
	}
	else
	{
		if (num==T->data)
		{
			return dele(T);
		}
		else if (num<T->data)
		{
			return deleteBTree(T->lchild,num);
		}
		else
		{
			return deleteBTree(T->rchild,num);
		}
		
	}
}

四、前序中序後序遍歷
void middVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
		middVisit(T->lchild);
		cout<<T->data<<"  ,  ";
		middVisit(T->rchild);
	}

}
void firstVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
		cout<<T->data<<"  ,  ";
		firstVisit(T->lchild);
		firstVisit(T->rchild);
	}
}
void lastVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
	
		lastVisit(T->lchild);
		lastVisit(T->rchild);
		cout<<T->data<<"  ,  ";
	}
}

五、構建
利用BST樹的插入操作,可以從空樹開始逐個插入每個結點,從而建立一棵BST樹
biTree CreateTree()
{
	biTree T=NULL;
	int num=0;
	cout<<"請輸入一次插入的值:";
	cin>>num;
	while (num!=-1)
	{
		InsertBST(T,num);
		cout<<"下一個插入的值(-1結束):";
		cin>>num;
	}
	cout<<"二叉樹建立完成\n";
	return T;
}
六、運行程序
#include"iostream"
using namespace std;

struct BiTNode 
{
	int data;
	struct BiTNode *lchild,*rchild;
};
typedef struct BiTNode BiTNode,*biTree;

/******************************************
函數名:biTree SearchBST(biTree T,int key)
功能:當二叉樹不空時將搜索值與根節點的關鍵字進行比較,若相等
查找成功,否則根據二者大小關係,分別在左子樹和右子樹上繼續進行查找
******************************************/
biTree SearchBST(biTree T,int key)
{
	//在根指針T所指的二叉排序樹中遞歸地查找某關鍵字等於key的數據元素
	//若查找成功,則返回指向數據元素節點的指針,否則,返回空指針
	if (T==NULL)
	{
		return NULL;
	}
	else
	{
		if (key==T->data)
		{
			return T;
		}
		else if (key<T->data)
		{
			return (SearchBST(T->lchild,key));
		}
		else
		{
			return(SearchBST(T->rchild,key));
		}
	}

}

/******************************************
函數名:void  InsertBST (biTree T , int key)
功能:在BST樹中插入一個新結點x時,若BST樹爲空,
則令新結點x爲插入後BST樹的根結點;
否則,將結點x的關鍵字與根結點T的關鍵字進行比較: 
① 若相等: 不需要插入;
②  若x.key<T->key:結點x插入到T的左子樹中;
③  若x.key>T->key:結點x插入到T的右子樹中。
由結論知,對於一個無序序列可以通過構造一棵BST樹
而變成一個有序序列。
由算法知,每次插入的新結點都是BST樹的葉子結點,
即在插入時不必移動其它結點,僅需修改某個結點的指針。

******************************************/
void  InsertBST (biTree &T , int key)
{	

	
	if (T==NULL)
	{
		biTree x;
		x=new BiTNode;
		x->data=key;
		x->lchild=x->rchild=NULL;
		T=x;
		cout<<"插入成功\n";
	}
	else
	{
		if (T->data==key)
		{
			cout<<"節點已存在\n"<<endl;
		}
		else if (key<T->data)
		{
			InsertBST(T->lchild,key);
		}
		else
		{		
			InsertBST(T->rchild,key);
		}
	}
	
}
/***************************************
函數名稱:biTree CreateTree()
功能:構建二叉樹
***************************************/
biTree CreateTree()
{
	biTree T=NULL;
	int num=0;
	cout<<"請輸入一次插入的值:";
	cin>>num;
	while (num!=-1)
	{
		InsertBST(T,num);
		cout<<"下一個插入的值(-1結束):";
		cin>>num;
	}
	cout<<"二叉樹建立完成\n";
	return T;
}

int dele(biTree &p)
{
	biTree q,s;
	if (p->lchild==NULL)
	{
		q=p;
		p=p->lchild;
		delete q;
	}
	else if (p->rchild==NULL)
	{
		q=p;
		p=p->rchild;
		delete q;
	}
	else
	{
		q=p;
		s=p->lchild;
		while(s->rchild)
		{
			q=s;
			s=s->rchild;
		}
		p->data=s->data;
		if (q!=p)
		{
			q->rchild=s->lchild;
		}
		else
		{
			q->lchild=s->lchild;
		}
		delete s;

	}
	return 1;
	
}
int deleteBTree(biTree &T,int num)
{
	if (T==NULL)
	{
		return 0;
	}
	else
	{
		if (num==T->data)
		{
			return dele(T);
		}
		else if (num<T->data)
		{
			return deleteBTree(T->lchild,num);
		}
		else
		{
			return deleteBTree(T->rchild,num);
		}
		
	}
}
void middVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
		middVisit(T->lchild);
		cout<<T->data<<"  ,  ";
		middVisit(T->rchild);
	}

}
void firstVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
		cout<<T->data<<"  ,  ";
		firstVisit(T->lchild);
		firstVisit(T->rchild);
	}
}
void lastVisit(biTree T)
{
	if (T==NULL)
	{
		;
	}
	else
	{
	
		lastVisit(T->lchild);
		lastVisit(T->rchild);
		cout<<T->data<<"  ,  ";
	}
}
int main()
{
    biTree T=CreateTree();
	cout<<"中序遍歷結果:\n";
	middVisit(T);
	cout<<endl;
	cout<<"前序遍歷結果:\n";
	firstVisit(T);
	cout<<endl;
	cout<<"後序遍歷結果:\n";
	lastVisit(T);
	cout<<endl;

	deleteBTree(T,7);
	cout<<"中序遍歷結果:\n";
	middVisit(T);
	cout<<endl;
    return 0;
}

七 、運行結果


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