试图在C ++中删除二进制搜索树节点

时间:2015-05-07 03:31:35

标签: c++

我的删除节点功能有问题。

void TreeNode::TreeRemove(TreeNode* &root, TreeNode* key){
TreeNode* par  = NULL;
TreeNode* curr = root;
while (curr != 0) {
    if (curr->GetData()->GetArea() == key->GetData()->GetArea()){
        if (!curr->GetLeft() && !curr->GetRight()){     //Remove leaf
            if (!par)
                root = NULL;
            else if (par->GetLeft() == curr)
                par->SetLeft(NULL);
            else
                par->SetRight(NULL);
        }
        else if (curr->GetLeft() && !curr->GetRight()) { //Remove node with only left child
            if (!par)
                root = curr->GetLeft();
            else if (par->GetLeft() == curr)
                par->SetLeft(curr->GetLeft());
            else
                par->SetRight(curr->GetLeft());
        }
        else if (!curr->GetLeft() && curr->GetRight()){  //Remove node with only right child
            if (!par)
                root = curr->GetRight();
            else if (par->GetLeft() == curr)
                par->SetLeft(curr->GetRight());
            else
                par->SetRight(curr->GetRight());
        }
        else {                                            //Remove node with two children

            TreeNode* succ = NULL;
            succ = curr->GetRight();
            while (succ->GetLeft() != 0)
                succ = succ->GetLeft();
            curr = succ;
            curr = curr->GetRight();
            TreeRemove(curr, succ);

        }
        return;
    }
    else if (curr->GetData()->GetArea() < key->GetData()->GetArea()){
        par  = curr;
        curr = curr->GetRight();
    }
    else {
        par  = curr;
        curr = curr->GetLeft();
    }
}
return;
}

到目前为止,除了这段代码之外,它都有效:

        else {                               //Remove node with two children

            TreeNode* succ = NULL;
            succ = curr->GetRight();
            while (succ->GetLeft() != 0)
                succ = succ->GetLeft();
            curr = succ;
            curr = curr->GetRight();
            TreeRemove(curr, succ);

        }

它实际上并没有产生错误。但是,在尝试实际删除具有两个子项的值时,它不会删除。我一直试图解决这个问题,但不能。

其他一切都很有效。

测试代码:

20
24.98
27.4955
32.7261
34
36.6606
37.609
38
44
47.444
52.5357
55
56.285
60.9687
61.8946
62.45
63
63
65.7267
69.8387
70.4002
70.993
72
72
80.271
84.8171
85
94
96
102
103.923
107.69
110
112.818
119.059
124
129.831
139.812
142.166
149.995
156.818
164.098
168
171
174.539
179.6
180.492
182
182
194.422
194.936
199.75
202.049
205
207
237.142
238.797
250.117
267.909
269.867
279
280
285
285.657
289.972
322
328.044
336
344
350
351.286
352
356.685
370
372.29
373.006
374.7
380
382.014
405
408
420
432.804
441.333
450
471.575
480.22
484
484
484.418
490.681
495
500
520.752
542.218
551
554.931
642.912
667
672
674.74
696.75
714
714
714.926
720
728
735
748
750
774.968
868
874
894.467
900
928
950.666
980
1008
1036
1075
1150
1190
1218
1260
1292
1295
1462
1845
1974
2500
Enter an area to search for: 1974
20
24.98
27.4955
32.7261
34
36.6606
37.609
38
44
47.444
52.5357
55
56.285
60.9687
61.8946
62.45
63
63
65.7267
69.8387
70.4002
70.993
72
72
80.271
84.8171
85
94
96
102
103.923
107.69
110
112.818
119.059
124
129.831
139.812
142.166
149.995
156.818
164.098
168
171
174.539
179.6
180.492
182
182
194.422
194.936
199.75
202.049
205
207
237.142
238.797
250.117
267.909
269.867
279
280
285
285.657
289.972
322
328.044
336
344
350
351.286
352
356.685
370
372.29
373.006
374.7
380
382.014
405
408
420
432.804
441.333
450
471.575
480.22
484
484
484.418
490.681
495
500
520.752
542.218
551
554.931
642.912
667
672
674.74
696.75
714
714
714.926
720
728
735
748
750
774.968
868
874
894.467
900
928
950.666
980
1008
1036
1075
1150
1190
1218
1260
1292
1295
1462
1845
1974
2500
Found it!

Do you want to quit(y/n)?

输入的数字应从列表中删除。它不是。但是,删除了没有两个子节点的其他数字。

主程序:

#include <iostream>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <string>
#include <fstream>
#include <stdexcept>
#include <treenode.h>
#include <shape.h>

using namespace std;

int main()
{
    string userYesNo;
    double userArea;
    int i = 0;

    vector<Rect> vRect;
    vector<Triangle> vTriangle;

    ifstream RectFile;
    ifstream TriFile;

    RectFile.open("Rsides.txt");
    TriFile.open("Tsides.txt");

    try {
        if (!RectFile.is_open())
                throw 1;
    }
    catch(int e){
        cout << "Could not open file Rsides.txt."  << endl
             << "Terminating program. Press enter" << endl
             << "to continue.";
        cin.ignore();
        return 0;
    }

    try {
        if (!TriFile.is_open())
                throw 1;
    }
    catch(int e){
        cout << "Could not open file Tsides.txt."  << endl
             << "Terminating program. Press enter" << endl
             << "to continue.";
        cin.ignore();
        return 0;
    }

    while(!RectFile.eof()) {
        Rect tempRect;

        double tempRX = -1;
        double tempRY = -1;

        RectFile >> tempRX;
        RectFile >> tempRY;

        tempRect.SetA(tempRX);
        tempRect.SetB(tempRY);

        if ((tempRect.CheckValidity(tempRX, tempRY))==true){
            vRect.push_back(tempRect);
        }
    }

    while(!TriFile.eof()) {
        Triangle tempTri;

        double tempTX = -1;
        double tempTY = -1;
        double tempTZ = -1;

        TriFile >> tempTX;
        TriFile >> tempTY;
        TriFile >> tempTZ;

        tempTri.SetA(tempTX);
        tempTri.SetB(tempTY);
        tempTri.SetC(tempTZ);

        if (((tempTri.CheckValidity(tempTX, tempTY, tempTZ))==true) && (tempTri.GetArea() != -1)){
            vTriangle.push_back(tempTri);
        }
    }

    RectFile.close();
    TriFile.close();

    TreeNode* root = NULL;
    TreeNode* newNode = root;
    TreeNode* nodeDelete = NULL;

    while(i<vRect.size()) {

        TreeNode* temp1 = new TreeNode;

        temp1->SetData(&vRect.at(i));

        root->TreeInsert(newNode, temp1);
        i++;

    }

    i = 0;

    while(i<vTriangle.size()) { //Same thing as above. However, this inserts in order.

        TreeNode* temp2 = new TreeNode;

        temp2->SetData(&vTriangle.at(i));
        //cout<<temp2->GetData()->GetArea()<<endl;

        root->TreeInsert(newNode, temp2);
        i++;

    }

    i = 0;

    root->PrintInOrder(newNode);

    while ((userYesNo != "Y") && (userYesNo != "y") && (userYesNo != "Yes") && (userYesNo != "yes")) {

        cout << "Enter an area to search for: ";
        int c = cin.peek();
        if (!isdigit(c)) {continue;}
        cin >> userArea;

        nodeDelete = newNode->TreeSearch(newNode, userArea);

        if (nodeDelete != NULL) {
            newNode->TreeRemove(newNode, nodeDelete);
            newNode->PrintInOrder(newNode);
            cout << "Found it!" << endl;
        }
        else {
            newNode->PrintInOrder(newNode);
            cout << "Not found!" << endl;
        }

        cout << endl << "Do you want to quit(y/n)?" << endl;
        cin >> userYesNo;
        cout << endl;

    }
    return 0;
}

以下是我正在使用的伪代码:

else                                   // Remove node with two children
            // Find successor (leftmost child of right subtree)
            suc = cur->right
            while (suc->left is not 0)
               suc = suc->left
            cur = Copy suc             // Copy successor to current node
            TreeRemove(cur->right, suc->key) // Remove successor from right subtree

1 个答案:

答案 0 :(得分:1)

在此代码中

        curr = succ;
        curr = curr->GetRight();
        TreeRemove(curr, succ);

您使用TreeRemove rootcurr key来呼叫succ。但是curr低于树中的succ,因此TreeRemove永远无法找到它来删除它。

我认为这意味着你需要重新思考你想要实现的目标。从代码中不完全清楚。也许再看看你正在使用的算法。