首先,BST節點的刪除分為幾種情況:
(a)當該節點為
葉子節點,則讓該節點的父節點指向其變為NULL,然后釋放節點;
(b)當該節點
不是葉子節點,但
左子樹或者右子樹為空,則:
(1)若左子樹為空,則讓該節點父節點指向其右節點;
(2)若右子樹為空,則讓該節點父節點指向其左節點。
(c)當該節點
不是葉子節點,且
左子樹和右子樹都不為空,則:
(1)在該節點的左子樹中找到最大節點Lmax(該節點必然是一個葉子節點),取出Lmax的值val,刪除Lmax;
(2)將 val 賦給該節點的值,即:root->val = val。
(3)判斷Lmax的父節點PreLmax的左節點是否等於Lmax,若是則:PreLmax->left = Lmax->left 否則: PreLmax->right = Lmax->left。
二叉搜索樹的刪除復雜度為O(h),h是二叉樹的高度。代碼如下:
/*刪除二叉搜索樹中的指定值的節點*/ node *deleteNode(node *root, int ele) { node *newroot = root; //指向新的根節點 node *presite = root; //指向要刪除節點的父節點 int pos = 0; //要刪除節點在其父節點的位置: -1:在左側 1:在右側 0:就是根節點 /*找到要刪除的元素在BST中的位置*/ while(root != NULL) { if(root->val > ele) { presite = root; root = root->left; pos = -1; } else if(root->val < ele) { presite = root; root = root->right; pos = 1; } else { break; } } if(root == NULL) { cerr<<"要刪除的節點不存在於BST中\n"; } else { //該節點有左子樹和右子樹 if(root->left!=NULL && root->right!=NULL) { cout<<"has left and right tree\n"; node *Lmax = root->left; //最大左子節點 node *PreLmax = root; //最大左子節點的父節點 while(Lmax->right != NULL) { PreLmax = Lmax; Lmax = Lmax->right; } root->val = Lmax->val; //替換root的值為最大左子樹節點值 if(PreLmax->left == Lmax) //root的左子樹最大節點是root的左節點 PreLmax->left = Lmax->left; else //root的左子樹最大節點不是root的左節點 PreLmax->right = Lmax->left; delete Lmax; Lmax = NULL; } //該節點的左子樹為空 else if(root->left == NULL && root->right != NULL) { cout<<"left tree is empty\n"; if(0 == pos) //在根節點 { newroot = root->right; } else if(1 == pos) //在右側 { presite->right = root->right; } else //在左側 { presite->left = root->right; } delete root; root = NULL; } //該節點的右子樹為空 else if(root->right == NULL && root->left != NULL) //site的右子樹為空 { cout<<"right tree is empty\n"; if(0 == pos) //在根節點 { newroot = root->left; } else if(1 == pos) //在右側 { presite->right = root->left; } else //在左側 { presite->left = root->left; } delete root; root = NULL; } //該節點為葉子節點 else { cout<<"leaf node\n"; if(0 == pos) //根節點 { cerr<<"BST只有一個節點且被刪除,該BST變為空樹\n"; delete root; root = NULL; } else if(1 == pos) //在右側 { presite->right = NULL; delete root; root = NULL; } else //在左側 { presite->left = NULL; delete root; root = NULL; } } } return newroot; }
