二叉搜尋樹的詳解(演算法導論讀書筆記)

來源:互聯網
上載者:User
文章目錄
  • 樹的尋找
  • 最大關鍵字元素和最小關鍵字元素
  •  節點的前驅和後繼
  •   插入
什麼是二叉搜尋樹?

一棵二叉樹的節點x,如果y是x左子樹中的一個節點,那麼y.key<x.key.如果y是x右子樹中的一個節點,那麼y.key>x.key

二叉樹的資料結構

typedef int data_t;typedef struct BST{data_t  data;struct BST *left;struct BST *right;struct BST *parent;}BST;

二叉搜尋樹的遍曆

我們可以通過一個簡單的遞迴演算法按序輸出二叉搜尋樹中的所有關鍵字,這種演算法稱為中序遍曆,類似的,先序遍曆輸出的根的關鍵字在其左右子樹的關鍵字之間,後續遍曆輸出根的值在其左右子樹的值之後

以下為二叉樹的中序遍曆的遞迴演算法與非遞迴演算法

void bst_nonrecur_inorder(BST *root)//use stack to store tree's node {stack<BST *> s_bst;while(s_bst.size() || root!=NULL){if(root!=NULL){s_bst.push(root);root = root->left;}else{root = s_bst.top();s_bst.pop();cout << root->data << " ";root = root->right;}}}void bst_inorder(BST *root){if(root==NULL)return ;else{bst_inorder(root->left);cout << root->data << " ";bst_inorder(root->right);}}

注意:如果x是一棵n個結點字樹的根,那麼遍曆該樹需要O(n)時間

二叉樹的查詢

我們經常需要尋找一個儲存在二叉搜尋樹中的關鍵字。除了search操作之外,還支援諸如minnum,maxinum,successor(求後繼節點),predecessor(前驅結點)的查詢操作

樹的尋找輸入指向樹根節點的指標和一個關鍵字k,如果這個檢點存在,bst_search返回一個指向關鍵字k的節點的指標,否則返回NULL下面為樹尋找的遞迴實現與迭代實現
//search a node in the binary-search-treeBST *bst_search(BST *root, data_t data){if(root==NULL || root->data== data)return root;if(data<root->data)return bst_search(root->left, data);elsereturn bst_search(root->right, data);}BST *bst_iterative_search(BST *root, data_t data){if(root==NULL || root->data == data)return root;while(root!=NULL && data!=root->data){if(data<root->data)root = root->left;else if(data>root->data)root = root->right;}return root;}

最大關鍵字元素和最小關鍵字元素從樹根開始沿著left孩子指標,直到遇到一個一個節點的left指標為NULL,那麼該節點的值就是該二叉搜尋樹的最小關鍵字。同理,從樹根沿著right孩子指標,直到遇到一個節點的right指標為NULL為止,那麼該節點的值就是該二叉搜尋樹的最大關鍵字以下為實現代碼

//return the minnest node of treeBST *bst_mininum(BST *root){if(root == NULL)return NULL;while(root->left!=NULL)root = root->left;return root;}//return the maxest node of treeBST *bst_maxinum(BST *root){if(root == NULL)return NULL;while(root->right!=NULL)root = root->right;return root;}

注,以上兩個演算法的時間複雜度都是O(logn) (n為輸得節點的個數)

 節點的前驅和後繼給定一棵二叉搜尋樹的一個節點,有時候需要按中序遍曆的次序尋找它的後繼。如果所有的關鍵字互不相同,則一個節點x的後繼是大於x.key的最小關鍵字的節點。尋找前驅過程分為兩部分:1. 如果x的右子樹非空,那麼x的後繼則是x右子樹的最左節點;2. 如果x的右子樹為空白且有一個後繼節點y,那麼y就是最底層祖先並且其左孩子也是一個祖先。為了找到y,只需從x開始沿樹而上知道遇到一個其雙親有左孩子的節點尋找節點的前驅則先判斷x節點的左子樹是否為空白,非空則前驅就是左子樹的最右節點,空則從x沿樹而上直到遇到一個其雙親都有右孩子的節點,那麼該節點就是x的前驅結點下面為實現代碼
BST *bst_successor(BST *node){if(node == NULL)return NULL;if(node->right!=NULL)//find successor in the leftest of the right subtreereturn bst_mininum(node->right);//else find it a node leftSubTree from his parentBST *y = node->parent;while(y!=NULL && node==y->right){node = y;y = y->parent;}return y;}BST *bst_predecessor(BST *node){if(node == NULL)return NULL;if(node->left!=NULL)return bst_maxinum(node->left);BST *y = node->parent;while(y!=NULL && node==y->left){node = y;y = y->parent;}return y;}
樹的插入與刪除

  樹的插入與刪除操作會引起二叉搜尋樹表示的動態集合的變化,一定要修改資料結構來反映這個變化,但修改要保持二叉樹搜尋樹的性質的成立

  插入要將一個新值插入到一棵二叉搜尋樹T中,需要調用bst_insert。該函數以關鍵字v作為輸入,在函數構造節點node,並將node->left=NULL,node->right=NULL插入過程為:從樹根開始,指標node記錄一條向下的簡單路錦,並尋找要替換新節點insert的NULL,該遍曆保持tmo作為node的雙親 
//insert a node into a binary-search-treeBST *bst_insert(BST *root, data_t data){BST *insert = NULL, *node = NULL, *tmp = NULL;insert = bst_newnode(data);  //make a node to insert  node = root;while(node)    //find pos to insert{tmp = node;if(data < node->data)node = node->left;elsenode = node->right;}insert->parent = tmp;if(tmp==NULL)    //tree root is emptyroot = insert;else {if(data < tmp->data) tmp->left = insert;elsetmp->right = insert;}return root;}

樹的刪除從一個二叉搜尋樹T中刪除一個節點z,這個過程取決與指向root和待刪除節點node,以下為該過程的四種情況 1. 如果node沒有左孩子,那麼有其右孩子來替換node,這個右孩子可以是NULL,也可以不是 2. 如果node僅有一個節點且該節點是左孩子,那麼用其左孩子來替換node 3. 否則node既有一個左孩子又有一個右孩子,我們要尋找node的後繼y,這個後繼位於node的右子樹中並且沒有左孩子,現在需要將y移除原來的位置進行拼接,並替換樹中的node 3.1. 如果y是z的node的右孩子,那麼用y替換node 3.2 否則,y位於z的右子樹中但並不是z的右孩子,這種情況下,先用y的右孩子替換y,然後用y替換node(最後步驟同3.1) 為了在二叉搜尋樹內移動子樹,定義一個函數bst_transplant,它用涼意可子樹替換一棵字數並成為雙親的孩子節點。以下實現為用一棵以v為根的子樹來替換一棵以u為根的子樹,節點u的雙親就變為節點v的雙親,並且最後v成為u的雙親的相應孩子

//replace subtree of u with subtree of vBST *bst_transplant(BST *root, BST *u, BST *v){if(u->parent==NULL)   //u is root root = v;else if(u->parent->right == u)  // u is his parent's right subtreeu->parent->right = v;elseu->parent->left = v;   //u is his parent's left subtreeif(v!=NULL)   //set v's parentv->parent = u->parent;return root;}
樹的刪除代碼如下
BST *bst_delete(BST *root, data_t data){BST *node = NULL, *y = NULL;node = bst_search(root, data);  //find the deleted nodeif(node==NULL)return NULL;if(node->left == NULL) //case 1root = bst_transplant(root, node, node->right);else if(node->right == NULL)//case 2root = bst_transplant(root, node, node->left);else {y = bst_mininum(node->right);  //find node's successorif(y->parent!=node)         //case 3  follow  make y's parent to node{root = bst_transplant(root, y, y->right);y->right = node->right;node->right->parent = y;}                            //case 3 y->parent == noderoot = bst_transplant(root, node, y);y->left = node->left;y->left->parent = y;}return root;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.