二叉搜尋樹或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉搜尋樹。二叉搜尋樹的特點之一即是其中序遍歷為公升序。
根據二叉搜尋樹的性質,每個結點的值都是大於其左子結點值(左子結點非空)並且小於其右子結點值(右子結點非空),因此可以考慮二分查詢的方法:比較目標值與當前結點值,如果目標值大於當前結點值,那麼說明目標值不可能存在於當前結點的左子樹中,應當再從其右子樹中去查詢;如果目標值小於當前結點值,那麼說明目標值不可能存在於當前結點的右子樹中,應當再從其左子樹中去查詢;如果目標值等於當前結點值,就返回當前結點,因此就不難寫出**了:
treenode* searchbst(treenode* root, int val)
if(root->val==val)return root; //如果目標結點值與當前結點值相同,就直接返回當前結點
if(root->valright=insertintobst(root->right,val);
else root->left=insertintobst(root->left,val);//如果目標結點值小於當前結點值,就在左子樹中進行查詢
return root; //返回結點
}
二叉搜尋樹的刪除是比較麻煩的,刪除結點還是需要先找到待刪除結點的位置,找到待刪除結點實際上就是二叉搜尋樹的查詢了,這裡就不多說了,主要說一下找到待刪除結點後該怎麼操作。這裡一共有以下幾種情況:
①待刪除結點沒有子結點;
②待刪除結點左子樹為空,右子樹非空;
③待刪除結點右子樹為空,左子樹非空;
④待刪除結點左右子樹皆非空。
第①種情況比較簡單,直接返回空結點即可,現在來說下其他情況:
對於第②種情況,舉個例子:刪除下面二叉搜尋樹中的1
那麼刪除後的結果就應該將2結點移到1結點,如下:
由此也可總結出第②種情況的刪除方法:從當前結點的右子結點開始,一直遍歷左子結點,來在當前結點的右子樹中找到最小值結點,然後將最小值賦值給當前結點值,再刪除最小值結點。
需要注意的是,最小值結點可能是葉子結點,也可能還有右子樹,如果是葉子節點,那麼直接讓該最小值結點的雙親結點的左子樹指標指向null即可;
如果最小值結點還有右子樹的話,如在上圖中繼續刪除3結點,就還需要再處理3結點的右子樹,那麼就只需要將最小值結點的右子樹接在最小值結點雙親結點的左子樹上即可,換句話說,就是將圖中的結點4接在結點3的雙親結點5的左子樹上。
除此之外,還有一種特殊情況,即是當前結點的右子結點就是最小值結點了,那麼說明其右子結點的左子樹必定為空了,此時只需將其右子結點的值賦值給當前結點,並將其右子結點的右子樹接到當前結點的右子樹上即可。
實現**如下:
//在右子樹中找到最小結點值來替換當前根結點值
treenode* rightmin=root->right;
treenode* lastmin=root; //儲存雙親結點
while(rightmin->left)
root->val=rightmin->val; //將找到的最小結點值賦值給根結點
if(lastmin==root)lastmin->right=rightmin->right; //如果根結點的右子結點就是右子樹中最小的了,即右子結點
的左子結點為空,就直接將右子結點的右子樹接到根結點右子樹上即可
else lastmin->left=rightmin->right; //否則就將最小值結點的右子樹接到最小結點的上乙個結點的左子樹上
第③種情況,左子樹非空,右子樹為空,刪除的方法與上述類似,就不多說了;
第④種情況,對於左右子樹均非空的情況,其實就既可以從左子樹中找到最大結點來取代當前結點,也可以從右子樹中找到最小結點來取代當前結點,兩種方法都是可以的。
綜合以上,**如下:
treenode* deletenode(treenode* root, int key)
root->val=rightmin->val; //將找到的最小結點值賦值給根結點
if(lastmin==root)lastmin->right=rightmin->right; //如果根結點的右子結點就是右子樹中最小的了,即右子結點的左子結點為空,就直接將右子結點的右子樹接到根結點右子樹上即可
else lastmin->left=rightmin->right; //否則就將最小值結點的右子樹接到最小結點的上乙個結點的左子樹上
}else //左子樹非空,右子樹空 或者 左右子樹均非空 均非空的情況下即可以在左子樹中找最大的也可以在右子樹中找最小的
root->val=leftmax->val; //將找到的最小結點值賦值給根結點
if(lastmax==root)lastmax->left=leftmax->left; //如果根結點的左子結點就是左子樹中最大的了,即左子結點的右子結點為空,就直接將左子結點的左子樹接到根結點左子樹上即可
else lastmax->right=leftmax->left; //否則就將最大值結點的左子樹接到最大結點的上乙個結點的右子樹上}}
else if(root->val>key)
root->left=deletenode(root->left,key); //如果當前結點值大於目標值,就從左子樹中刪除目標值
else root->right=deletenode(root->right,key); //如果當前結點值小於目標值,就從右子樹中刪除目標值
return root;
}
排序二叉樹or搜尋二叉樹or查詢二叉樹
排序二叉樹,搜尋二叉樹,查詢二叉樹都是乙個意思,只是叫法不同而已。下面的文章中我們統稱為排序二叉樹。本文主要是針對高中資訊學,因此其中不涉及到指標,所有需要用指標的地方都直接使用陣列進行模擬。排序二叉樹定義 1 若左子樹不空,則左子樹上所有結點的值均小於或等於它的根結點的值 2 若右子樹不空,則右子...
排序二叉樹or搜尋二叉樹or查詢二叉樹
排序二叉樹,搜尋二叉樹,查詢二叉樹都是乙個意思,只是叫法不同而已。下面的文章中我們統稱為排序二叉樹。本文主要是針對高中資訊學,因此其中不涉及到指標,所有需要用指標的地方都直接使用陣列進行模擬。排序二叉樹定義 1 若左子樹不空,則左子樹上所有結點的值均小於或等於它的根結點的值 2 若右子樹不空,則右子...
二叉樹 還原二叉樹 二叉搜尋樹
先序遍歷的特點 先遍歷根結點,再遍歷左子樹,最後再遍歷右子樹 中序遍歷的特點 先遍歷左子樹,再遍歷根結點,最後再遍歷右子樹 後序遍歷的特點 先遍歷左子樹,再遍歷右子樹,最後再遍歷根結點 舉例 先序遍歷 a b d f g h i e c 中序遍歷 f d h g i b e a c 如上,根據先序遍...