【演算法總結】二叉排序樹
二叉排序樹是一棵特殊的二叉樹,它是一棵二叉樹但同時滿足如下條件:對於樹上任意乙個結點,其上的數值必大於等於其左子樹上任意結點數值,必小於等於其右子樹上任意結點的數值。
我們從二叉樹的插入開始了解其建樹方式,對二叉排序樹插入數字 x:
1.若當前樹為空,則 x 為其根結點。
2.若當前結點大於 x,則 x 插入其左子樹;若當前結點小於 x,則 x 插入其右子樹;若當前結點等於 x,則根據具體情況選擇插入左右子樹或者直接忽略。
以插入 4、2、6、1、3 為例,其二叉排序樹變化情況如下圖。
由於各個數字插入的順序不同,所得到的二叉排序樹的形態也很可能不同, 所以不同的插入順序對二叉排序樹的形態有重要的影響。但是,所有的二叉排序樹都有乙個共同的特點:若對二叉排序樹進行中序遍歷,那麼其遍歷結果必然是乙個遞增序列,這也是二叉排序樹名字的來由,通過建立二叉排序樹就能對原無序序列進行排序,並實現動態維護。
insert函式的返回值是node指標這一點非常重要,因為要往前拱就必須「生長」左右子結點。
例 3.5 二叉排序樹
ac**
#include#includestruct 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 必須是鍊錶儲存。動態查詢表就可以同時滿足這兩者。動態查詢表的特點是表結構本身在查詢過...