查找(二)——基於二叉排序樹的查找


    導論:首先,沿着二分查找的思路,我們構造一種二叉樹來查找,這種二叉樹的左子樹結點都小於根節點,右子樹節點都大於根節點,這樣一來,所有結點算是都排好序了,接下來就可以查找

 

基於二叉排序樹的查找

 

一.二叉排序樹的定義

所謂二叉排序樹是一個什么樣的東西,我們得弄清楚,以下是二叉排序樹的定義:

  1.若它的左子樹非空,則左子樹上所有節點的值都小於根節點的值

  2.若它的右子樹非空,則右子樹上所有結點的值都大於根節點的值

  3.它的左子樹和右子樹也是一顆二叉排序樹

 

  有了定義,很多東西就都會顯而易見了:

  1.二叉排序樹並不是一顆完全二叉樹

  2.和二叉判定樹的對比:二叉判定樹是一種特殊的二叉排序樹,二叉判定樹多了一個限定條件:左右子樹的節點數目相差最多不能超過1個(小雨或等於1)

      3.二叉排序樹又名二叉查找樹

   

  好了,到這里給出二叉排序樹的定義

  

typedef struct  _TreeNode
{
	struct _TreeNode *leftNode;
	struct _TreeNode *rightNode;
	TypeData data;
}TreeNode,*TreeRoot;

  

 

 

 

二.二叉排序樹的插入

  和堆的建立和維護類似,我們首先想解決的一個問題就是:已經有了一顆二叉排序樹,怎樣做到將一個值插入正確的位置,

  給出二叉樹的插入定義

  

TreeNode* Insert_Tree(TreeRoot &root,TypeData key)
{
	if (!root)
	{
		TreeNode *node=new TreeNode;
		node->data=key;
		node->leftNode=nullptr;
		node->rightNode=nullptr;
		root=node;
		return root;
	}
	else if (root->data==key)
	{
		return root;
	}
	else if (root->data<key)
	{
		return (Insert_Tree(root->rightNode,key));
	}
	else if (root->data>key)
	{
		return(Insert_Tree(root->leftNode,key));
	}

}

  

這里是用遞歸實現的二叉排序樹的插入,要注意以下幾點:

 

    遞歸開始返回的終結點有兩個:

                  1.當根節點為null時

                  2.根節點的data值和key相等,這個時候就不需要插入了

    插入完畢返回插入位置的結點

 

三.二叉排序樹的建立

    所謂二叉排序樹的建立,也就是通過向一個空節點不斷地插入結點來建立一顆二叉排序樹,通過遞歸地插入,可得

void Create_Tree(TreeRoot& root)
{
	TypeData key;
	while (std::cin>>key)
	{
		Insert_Tree(root,key);
	}
}

  

四.通過二叉排序樹進行查找

    這里,有兩種方式,遞歸和非遞歸的

    首先是遞歸的

TreeNode *find_InTree(TreeRoot root,TypeData key)
{
	if (root)
	{
		if (root->data==key)
		{
			return root;
		}
		else if (root->data>key)
		{
			return find_InTree(root->leftNode,key);
		}
		else
		{
			return find_InTree(root->rightNode,key);
		}
	}
	return nullptr;
}

  然后是非遞歸的,用while循環代替遞歸達到遞歸的作用

TreeNode *find_InTree2(TreeRoot root,TypeData key)
{
	TreeNode* p=root;
	while (p)
	{
		if (p->data==key)
		{
			return p;
			break;
		}
		else if (p->data>key)
		{
			p=p->leftNode;
		}
		else
		{
			p=p->rightNode;
		}
	}
	return nullptr;
}

  

 

 

最后,簡單地分析一下查找的時間復雜度吧!

    二叉排序樹的插入過程:很明顯,二叉排序樹過程最好情況是O(log2(n)),最差情況是O(n),最差的情況時:二叉樹變為一顆只有左子樹或者只有右子樹的二叉樹,整個插入過程也退化成為順序插入

    二叉排序樹的創建過程:很明顯,假設有n個數,建立二叉排序樹就要while循環n次插入過程,也就是說創建過程為O(nlog2(n))~O(n²)之間

    二叉排序樹的查找過程:很明顯,基於二叉排序樹的查找過程和二叉排序樹的插入過程類似,時間復雜度也為O(log2(n))到O(n)之間

 

最后,程序執行過程使這樣的:

 

排序二叉樹的創建過程;

排序二叉樹的查找過程;

這樣看來,整個過程的時間復雜度為O(nlog2(n)到O(n²))之間,但是實際上表述的時候我們通常忽略創建過程,只考慮二叉樹的查找過程,這樣看來的話,整個過程的時間復雜度為O(log2(n))到O(n)之間

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM