演算法總結 二叉排序樹

2022-07-05 18:30:14 字數 4038 閱讀 1298

【演算法總結】二叉排序樹

二叉排序樹是一棵特殊的二叉樹,它是一棵二叉樹但同時滿足如下條件:對於樹上任意乙個結點,其上的數值必大於等於其左子樹上任意結點數值,必小於等於其右子樹上任意結點的數值。

我們從二叉樹的插入開始了解其建樹方式,對二叉排序樹插入數字 x:

1.若當前樹為空,則 x 為其根結點。

2.若當前結點大於 x,則 x 插入其左子樹;若當前結點小於 x,則 x 插入其右子樹;若當前結點等於 x,則根據具體情況選擇插入左右子樹或者直接忽略。

以插入 4、2、6、1、3 為例,其二叉排序樹變化情況如下圖。

由於各個數字插入的順序不同,所得到的二叉排序樹的形態也很可能不同, 所以不同的插入順序對二叉排序樹的形態有重要的影響。但是,所有的二叉排序樹都有乙個共同的特點:若對二叉排序樹進行中序遍歷,那麼其遍歷結果必然是乙個遞增序列,這也是二叉排序樹名字的來由,通過建立二叉排序樹就能對原無序序列進行排序,並實現動態維護。 

insert函式的返回值是node指標這一點非常重要,因為要往前拱就必須「生長」左右子結點。

例 3.5 二叉排序樹

ac**

#include#include

struct node//

樹結點結構體

tree[110];//

靜態記憶體分配陣列

int loc;//

靜態陣列中被使用元素的個數,方便定位結點位置

node *creat() //

申請乙個結點空間,返回指向其的指標

void postorder(node *t)//

後序遍歷

void inorder(node *t)//

中序遍歷

void preorder(node *t)//

前序遍歷

node* insert(node *t, int x)//

插入數字

else

if (x < t->c) t->lchild = insert(t->lchild, x);//

若x數值小於根結點,插入到左子樹

else

if (x > t->c) t->rchild = insert(t->rchild, x);//

若x數值大於根結點,插入到右子樹

return t;//

返回根結點指標,x數值和根結點相同時,應題目要求直接忽略

}int

main()

preorder(t);

//前序遍歷

printf("\n"

); inorder(t);

//中序遍歷

printf("\n"

); postorder(t);

//後序遍歷

printf("\n"

); }

return0;

}

#include#include

#include

using

namespace

std;

int n, loc;//

元素總數,下標

struct

node

t[105

];node*create()

node* insert(int num, node*root)

else

if (root->x > num)root->l = insert(num, root->l);

else

if (root->x < num)root->r = insert(num, root->r);

return

root;

}void preorder(node*root)

void inorder(node*root)

void postorder(node*root)

intmain()

preorder(tree);

printf("\n

");inorder(tree);

printf("\n

");postorder(tree);

printf("\n

");}

return0;

}

二刷在學習了二叉排序樹的建立和三種方式的遍歷以後,我們還要接觸一種特殊的樹操作——判斷兩棵二叉樹是否相同。

判斷兩棵樹是否相同,我們不能簡單的用某一種遍歷方式去遍歷兩棵樹,並判斷遍歷的結果是否相同,這種方法是錯誤的。由於一種遍歷順序並不能唯一地確定一棵二叉樹,所以兩棵不同的樹的某一種遍歷順序是可能相同的。如數字相同,插入順序不同而建立的兩棵二叉排序樹,它們的中序遍歷一定是一樣的。但在之前例題中我們已經看到,包括中序遍歷在內的兩種遍歷結果可以唯一得確定一棵二叉樹,那麼我們只需對兩棵樹進行包括中序遍歷在內的兩種遍歷,若兩種遍歷的結果都相同,那麼就可以判定兩棵樹是完全相同的。 

例 3.6 二叉搜尋樹(題目要求就是判斷兩顆二叉排序樹是否相同,二叉搜尋樹就是排序樹)

ac**

#include#include

struct node//

樹結點結構體

tree[110];//

靜態記憶體分配陣列

int loc;//

靜態陣列中被使用元素的個數,方便定位結點位置

node *creat() //

申請乙個結點空間,返回指向其的指標

char str1[25], str2[25];//

儲存二叉排序樹的遍歷結果,將每一棵樹的前序遍歷得到的字串和中序遍歷得到的字串連線,得到遍歷結果字串

int size1, size2;//

儲存在字元陣列中的遍歷得到的字元個數

char * str;//

當前正在儲存的字串

int *size;//

當前正在儲存的字串的字元個數

void postorder(node *t)//

後序遍歷

void inorder(node *t)//

中序遍歷

node* insert(node *t, int x)//

插入數字

else

if (x < t->c) t->lchild = insert(t->lchild, x);//

若x數值小於根結點,插入到左子樹

else

if (x > t->c) t->rchild = insert(t->rchild, x);//

若x數值大於根結點,插入到右子樹

return t;//

返回根結點指標,x數值和根結點相同時,應題目要求直接忽略

}int

main()

}return0;

}

同樣的,我們也可以選擇中序和後序的排序結果共同對兩棵樹進行判定。但是請注意,在選擇的兩種遍歷方式中必須要包括中序遍歷。如在資料結構中所講的,只有包括中序的兩種遍歷順序才能唯一的確定一棵二叉樹。

最後,我們對二叉排序樹的刪除作適當的補充。二叉排序樹的刪除在機試題中考察的概率非常小,在之前我們已經得到的機試題中沒有對其進行任何的考察。

要刪除二叉排序樹上的某乙個結點,我們按如下步驟進行:

1.利用某種遍歷找到該結點。

2.若該結點為葉子結點,則直接刪除它,即將其雙親結點中指向其的指標改為 null。釋放該節點空間。

3.若該結點僅不存在右子樹,則直接將其左子樹的根結點代替其位置後,刪除該結點。即將其雙親結點指向其的指標改為指向其的左子樹樹根。

4.若該節點存在右子樹,則找到右子樹上最右下的結點(即中序遍歷中該子樹上第乙個被遍歷到的結點),將被刪除結點的數值改為右子樹上最右下結點的數值後,刪除最右下結點。

刪除二叉樹的原理非常簡單,即刪除該結點後,其中序遍歷依然保持關鍵字遞增的順序,只要符合這個條件,不同於上述規則的刪除也是可行的。 

排序演算法 二叉排序樹

二叉排序樹的基本思想是將序列中的數讀入乙個二叉樹,在讀入時遵循一定的規則 比如,如果二叉樹的乙個節點有左子節點,那麼左子節點一定比父節點的值小 如果乙個節點有右子節點,那麼右子節點一定比父節點的值大。在二叉排序樹製造完成後,通過採用中序遍歷的方法讀取二叉樹節點的值到序列中,就可以得到乙個公升序序列。...

查詢演算法 二叉排序樹

二叉排序樹,又稱二叉查詢樹,是一種對排序和查詢都很有用的特殊二叉樹 定義二叉排序樹或者是一棵空樹,或者具有以下定義 1 若左子樹不為空,左子樹上所有結點值均小於根結點值 2 若右子樹不為空,右子樹上所有結點值均大於根結點值 3 左右子樹也分別為二叉排序樹。遞迴定義。有定義可得性質 中序遍歷二叉樹可得...

二叉排序樹

在複習資料結構,把這個東西總結一下。這種結構是動態查詢表,這種動態是相對靜態查詢 順序查詢,折半查詢,分塊查詢等 來說的。對於各種靜態鍊錶,要達到查詢複雜度為o logn 必須要求有序 而要使插入刪除複雜度為o 1 必須是鍊錶儲存。動態查詢表就可以同時滿足這兩者。動態查詢表的特點是表結構本身在查詢過...