在資料的查詢這個問題上,如果查詢的資料集是有序線性表,並且是順序儲存的,查詢可以使用折半、插值、斐波那契等查詢演算法實現,可惜,因為有序,在插入和刪除操作上,就需要耗費大量的時間。
那麼有沒有一種可以使得插入和刪除的效率不錯,又可以比較高效地實現查詢的演算法呢?也就是說有沒有一種演算法能夠使用與動態查詢。
動態查詢:在查詢時插入或者刪除的查詢表稱為動態查詢表。
所以就引入了二叉排序樹,它是這樣的乙個二叉樹:
根據上面的性質可以知道,對這棵二叉排序樹中序遍歷就得到了乙個公升序的序列。但是構造乙個二叉排序樹的目的,並不是為了排序,而是為了提高查詢和插入刪除的速度。
樹結構結點定義:
typedef struct bitnodebitnode, *bitree;
查詢實現:查詢成功,返回查詢到的結點的指標,查詢不成功,返回查詢路徑上最後的乙個結點。
//f是當前根結點t的父結點,當查詢失敗時返回這個父結點bool searchbst(bitree t, int key, bitree f, bitree *p)
if (t->data == key) //查詢成功
else if (key < t->data)
else
}
這裡為什麼要返回查詢路徑上的最後乙個結點:因為在插入操作的時候,也需要用到查詢,而插入的點正好是查詢路徑上的最後乙個結點也就是把要插入的結點作為這個最後結點的孩子。
//插入新結點的時候,要先查詢,找到應該插入的位置bool insertbst(bitree *t, int key)
else if(p->data > key)
else
return true;
} else //查詢成功,要插入的元素已經存在,插入失敗
}
再看刪除操作:
如果要刪除的結點是葉子結點,那麼好,直接就刪除了。(因為引數是指標的指標,所有要刪除乙個結點,不用找到它的父結點)
如果要刪除的結點僅有左孩子或者僅有右孩子,那麼直接讓左子樹或者右子樹繼承。
如果有右孩子有左孩子,那麼有其直接前驅替代這個結點,然後刪除其直接前驅(之前前驅肯定只有乙個孩子或者沒有孩子,回到上面兩個問題)
注:使用直接後繼代替當前結點也是可以的。
//刪除後的指標要從被調函式中帶出來bool deletebst(bitree *t, int key)
if (key == (*t)->data)
else if((*t)->data > key)
else }
void delete(bitree *p)
else if((*p)->lchild == null)
else //有左孩子和右孩子
//while
(*p)->data = s->data;
if(q != (*p))
else
free(s);
}}
總結:我們構建二叉排序樹的目的就是能夠在有序的情況下快速的查詢,同時在插入或者刪除的時候又不要有太高的複雜度。但是給定乙個陣列序列,構建的二叉排序樹是不唯一的,他別陣列有序的情況下,構建的二叉排序樹是單邊樹,這樣的查詢的時間複雜度已經退化到了o(n)。所以我們要防止這種單邊樹的產生。盡量是樹的左子樹和右子樹的高度相同。這就是二叉平衡樹。
資料結構 二叉排序樹
二叉排序樹是一種特殊結構的二叉樹,它作為一種表的組織手段,通常被稱為 樹表。可以作為一種排序和檢索的手段。定義 二叉排序樹或是空樹,或是具有下述性質的二叉樹 其左子樹上所有結點的資料值均小於根結點的資料值 右子樹上所有結點的資料值均大於或等於根結點的資料值。左子樹和右子樹又各是一棵二叉排序樹。對二叉...
資料結構 二叉排序樹
二叉排序樹 binarysorttree 具有下列性質的二叉樹 1 若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值 2 若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值 3 左 右子樹也分別為二叉排序樹 include includeusing namespace std type...
資料結構 二叉排序樹
如果需要乙個滿足 支援排序性 高效插入 刪除操作 高效查詢的資料結構,怎麼做?先看看一些簡單的資料結構 1 排序順序表 陣列 查詢可以採用折半查詢演算法,時間效率為o log2n 插入 刪除操作的時間複雜度為o n 資料量大時,效率太低。2 排序單鏈表 只能採用順序查詢,時間複雜度為o n 不能採用...