Tree Delete Node in a BST

https://leetcode.com/problems/delete-node-in-a-bst/#/description
題目大意是實現在一個二叉樹中刪除一個節點的算法

要刪除二叉搜索樹中的某個節點p需要考慮三種情況:
1)p有兩顆非空子樹
2)p是樹葉
3)p是只有一顆非空子樹

刪除p節點的思路
1)要刪除的節點p具有兩顆非空子樹。先將該節點的元素替換為它的左子樹的最大元素或右子樹的最小元素。
2)要刪除的節點是葉子節點 。處理的方法是釋放該節點空間,若是根節點,則令根為NULL。
3 ) 要刪除的節點p只有一顆子樹。如果p沒有節點(即p是根節點),則p的唯一子樹的根節點成為新的搜索樹的根節點。如果p有父節點pp,則修改pp的指針域,使得它指向p的唯一孩子,然后釋放節點p。

以下是我實現的代碼

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        root = deleteNodeitem(root, key);
        return root; 
    }
    
    TreeNode* deleteNodeitem(TreeNode* root, int key){
       
        TreeNode* p = root;//the keynode to delete
        TreeNode* pp = root;//parentNode of the keynode
        TreeNode* s;//the node to replace the keynode
        TreeNode* ps;//parent node of replacenode
         
        //findout the keynode p and its parant node pp
        while((p != NULL)&&(p->val != key)){
            pp = p;
            if(key > p->val){
               p = p->right;    
            }else if(key < p->val){
               p = p->left;
            }
        }
         
        if(p == NULL){
            return root;
         }
       
        //state1 node p have 2 nonull childnode
        if((p->left!=NULL)&&(p->right!=NULL)){
            //find the biggest node in the right tree
            s = p->right;
            ps = p;
            while(s->left != NULL){
                ps = s;
                s = s->left;
            }
           
           TreeNode q = {s->val}; q.left = p->left; q.right = p->right;
            if(pp->left == p){
                pp->left = &q;
            }else if(pp->right == p){
                pp->right = &q;
            }else if(p == root){//要刪除的節點就是根節點
                pp->val = q.val;
                cout<< "要刪除的節點就是根節點" <<endl;
            }
            
            //make the s node to delete 找出節點s所對應的父節點
            if(ps != p){
                pp = ps;
            }else if((p == ps)&&(p!=root)){//當s的父節點即為p節點時
                pp = &q;
                cout<< "當s的父節點即為p節點時" <<endl;
            }
            p = s;//it must one left child of p if p has child
        }
        
        //statue2 node p have at most one nonull childnode
        TreeNode* pc = p;//the child of p , if it has. 
        if(p->left != NULL){
            pc = p->left;
        }else if(p->right != NULL){
            pc = p->right;
        }else{
            pc = NULL;//p has no child
        }
    
        if(pp->left == p){
            pp->left = pc;
        }else if(pp->right == p){
            pp->right = pc;
        }else{
            root = pc;//根節點就是需要刪除的節點
        }
        //  delete p;
        return root;
    }
};

可見代碼還是相對繁瑣的,下面是其他網友提供的更簡潔的算法,大體思路是一樣的但利用遞歸代碼量大大的減少

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return nullptr;
        if (root->val == key) {
            if (!root->right) {
                TreeNode* left = root->left;
                delete root;
                return left;
            }
            else {
                TreeNode* right = root->right;
                while (right->left)
                    right = right->left;
                swap(root->val, right->val);    
            }
        }
       //利用遞歸找出左右子樹中要刪除的節點,并利用該節點的右子樹中的左子樹的最小節點替換掉要被刪除的節點
        root->left = deleteNode(root->left, key);
        root->right = deleteNode(root->right, key);
        return root;
    }
};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • 以下是數據結構部分的主要知識點的思維導圖 在這段時間基本上刷的都是跟二叉樹有關的題目,所以下面主要針對二叉樹部分進...
    衣忌破閱讀 462評論 0 0
  • 樹的概述 樹是一種非常常用的數據結構,樹與前面介紹的線性表,棧,隊列等線性結構不同,樹是一種非線性結構 1.樹的定...
    Jack921閱讀 4,466評論 1 31
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結點至多有m個孩子。 除根結點和葉子結點外,其它每個結點至少有m...
    文檔隨手記閱讀 13,278評論 0 25
  • 基于樹實現的數據結構,具有兩個核心特征: 邏輯結構:數據元素之間具有層次關系; 數據運算:操作方法具有Log級的平...
    yhthu閱讀 4,295評論 1 5
  • 風落了一地 你走了很遠 我再看不見你的背影
    Lqrs閱讀 128評論 0 1