順序儲存的線性表查詢我們可以使用折半、插值、斐波那契等查詢演算法來實現,因為有序,所以在插入和刪除上就需要耗費大量的時間,今天要討論的演算法既可以獲得不錯的插入刪除效率,也可以比較高效的實現查詢——二叉排序樹。
二叉排序樹又叫二叉查詢樹,它或者是一棵空樹,或者是具有下列性質的二叉樹。
1、如果它的左子樹不為空,則左子樹上所有節點的值均小於它的根節點的值。
2、如果它的右子樹不為空,則右子樹上所有節點的值均大於它的根節點的值。
3、它的左右子樹也分別為二叉排序樹。
從二叉排序樹的定義可知,左子樹節點一定比雙親節點小,右子樹節點一定比雙親節點大。構造一顆二叉樹的目的並不是為了排序,而是為了提高插入和刪除關鍵字的速度。畢竟在乙個有序資料集上的查詢,速度=總是要快於無序的資料集的。
二叉排序樹的查詢
typedef struct binode
;typedef struct binode* bitree;
/*遞迴查詢二叉排序樹t中是否存在key*/
/*指標f指向t的雙親,其初始呼叫值為null*/
/*若查詢成功,則指標p指向該資料元素節點,並返回true*/
/*指標p指向查詢路徑上訪問的最後乙個節點,並返回false*/
status searchbst(bitree t, int key, bitree f, bitree* p)
else if (key == t->data)
else if(key < t->data)
else
}
**很簡單,不再贅述。接下來看下二叉排序樹的插入操作
二叉排序樹的插入
/*當二叉排序樹中不存在關鍵字等於key的資料元素時,插入key並返回true,否則返回false*/
status insertbst(bitree t, int key)
else if (key < p->data)
else
return true;
} else
}
插入的過程就是構造二叉排序樹的過程。
二叉排序樹的刪除
當我們想刪除二叉排序樹的節點時,按照孩子節點的數量可分為以下三種情況:
1、葉子節點,直接刪除即可
2、僅有左子樹或右子樹的節點,刪除該節點,將它的左子樹或右子樹移動到刪除節點的位置即可
3、既有左子樹又有右子樹,這時我們可以對二叉排序樹中序遍歷,得到待刪除節點的前驅和後繼節點,用前驅或者後繼節點來代替原來待刪節點的位置。
實現演算法如下:
status delete(bitree p)
else if (p->lchild == null)
else
p->data = s->data;
if(p != q)
else
free(s);
} return true;
}status deletebst(bitree t, int key)
else
else if (key < t->data)
else
}}
上述**中我們是使用帶刪除節點的前驅來替換待刪節點,使用後繼節點也是一樣的,這裡不再贅述。
總結:
二叉排序樹保持了鏈式儲存結構在執行插入和刪除操作時不需要移動元素的優點,只要找到合適的插入和刪除位置後,僅需修改鏈結指標即可。對於二叉排序樹的查詢,走的就是從根節點到要查詢節點的路徑,比較次數等於給定的節點在二叉排序樹中的層數,最少為1次,最多也不會超過樹的深度。因此其時間複雜度為o(logn)。
二叉排序樹
在複習資料結構,把這個東西總結一下。這種結構是動態查詢表,這種動態是相對靜態查詢 順序查詢,折半查詢,分塊查詢等 來說的。對於各種靜態鍊錶,要達到查詢複雜度為o logn 必須要求有序 而要使插入刪除複雜度為o 1 必須是鍊錶儲存。動態查詢表就可以同時滿足這兩者。動態查詢表的特點是表結構本身在查詢過...
二叉排序樹
name 二叉排序樹相關操作 author unimen date 2011 10 8 13 14 21 刪除結點比較麻煩,總結如下 4大種情況 1 結點p無右孩子 將該點的左孩子變為其在雙親中的同位孩子 1 p為其雙親的左孩子時將其的左孩子變為雙親的左孩子 2 p為其雙親的右孩子時將其的左孩子變為...
二叉排序樹
include include include include struct tree node void insert node struct tree node int void pre order struct tree node void in order struct tree node ...