【问题标题】:Sorting an array using a Binary Search Tree in C++在 C++ 中使用二叉搜索树对数组进行排序
【发布时间】:2020-07-19 03:48:21
【问题描述】:

我正在尝试编写一个对数组的整数元素进行排序的程序,使用二叉搜索树 (BST) 作为支持数据结构。 这个想法是,一旦给定数组,就可以使用 BST 对其元素进行排序;例如:

如果我的数组是:{120, 30, 115, 40, 50, 100, 70}

然后我像这样构建一个 BST:

一旦有了这个 BST,我就可以进行中序树遍历,从最低到最高元素按顺序触摸每个节点并修改数组。 结果将是一个排序数组 {30, 40, 50, 70, 100, 115, 120}

我写了这段代码,但我不明白我犯的错误在哪里。 它编译没有任何错误,但显然它有问题:

#include<iostream>
using namespace std;

struct Node
{
    int label;
    Node* left;
    Node* right;
};


void insertSearchNode(Node* &tree, int x)       //insert integer x into the BST
{
    if(!tree){
        tree = new Node;
        tree->label = x;
        tree->right = NULL;
        tree->left = NULL;
        return;
    }
    if(x < tree->label) insertSearchNode(tree->left, x);
    if(x > tree->label) insertSearchNode(tree->right, x);
    return;
}

void insertArrayTree(int arr[], int n, Node* &tree)     //insert the array integer into the nodes label of BST
{
    for(int i=0; i<n; i++){
        insertSearchNode(tree, arr[i]);
    }
    return;
}

int insertIntoArray(int arr[], Node* &tree, int i)      //insert into the array the node label touched during an inorder tree traversal
{
    i=0;
    if(!tree) return 0;
    i += insertIntoArray(arr, tree->left, i) +1;
    arr[i] = tree->label;
    i += insertIntoArray(arr, tree->right, i) +1;
    return i;

}

int main()
{
    Node* maintree;
    maintree = NULL;
    int num;
    cin>>num;
    int arr[num];
    for(int i=0; i<num; i++){    //initialize array with num-elements
     cin>>arr[i];
    }
    insertArrayTree(arr, num, maintree);    //insert elements into BST
    int index;
    insertIntoArray(arr, maintree, index);  //modify array sorting his elements using the BST

    for(int y=0; y<num; y++) cout<< arr[y] << ' ';

    return 0;
}

我希望我的问题足够清楚。 任何帮助/建议将不胜感激!

谢谢:)

【问题讨论】:

  • 我只是看了你的代码,但为什么insertIntoArray 立即将其i 参数设置为0
  • @BradyDean 我试图弄清楚如何在数组的正确位置插入 BST 的元素,但现在我正在查看函数 insertIntoArray 似乎不起作用。如果它在 tree==NULL 时返回 -1 而不是 0 可能会起作用吗? (对不起我的英语,希望清楚)
  • 我想让你的代码正常工作,我只是想弄清楚insertIntoArray。你忘了检查x == tree-&gt;label 是否也在insertSearchNode 中。
  • 不错的开始。当你让它工作时,你应该在codereview.stackexchange.com PS 上获得代码审查。他们只会审查工作代码,因此需要先修复它。
  • 是的,确实是一个不错的开始。但请注意,BST 通常不是用于“排序”数据的东西,BST 是一种数据结构,它以有序的顺序保存数据,因此只需要按顺序遍历以输出数据排序。如果您不需要数组,则无需仅使用一个来填充 BST。 std::map 通常实现为红黑树。如果您使用的是数组,您可以简单地使用std::sort 对其进行排序。很多选择。

标签: c++ algorithm sorting binary-search-tree computer-science


【解决方案1】:

似乎唯一错误的是insertIntoArray()

第一个问题是您将一个未初始化的变量作为参数传递:

int index;
insertIntoArray(arr, maintree, index);

为什么。您开始在零处填充数组,因此传递零(并摆脱索引变量)。

insertIntoArray(arr, maintree, 0);

我无法完全破译您的insertIntoArray() 版本。但这个版本似乎可以工作。

int insertIntoArray(int arr[], Node* tree, int i)
{
    // If you fall of a leaf then there is nothing to do.
    // So simply return the index as it has not changed.
    if (!tree) {
        return i;
    }


    // Since it is a BST we always go left first.
    // The return value is where we have reached when we
    // have inserted all the left values. 
    i = insertIntoArray(arr, tree->left, i);

    // Now put the current value in and increment the index position.
    arr[i] = tree->label;
    ++i;

    // Now do the right sub-tree.
    i = insertIntoArray(arr, tree->right, i);

    // Return the point index we have reached so far.
    return i;
}

好的。所以它应该工作。 但是这并不意味着这都是好的 C++ 代码。你真的应该审查这段代码。

【讨论】:

  • 我的 insertIntoArray 函数显然根本不起作用,谢谢您的解释。我可以问你代码审查是什么意思,它有什么好处?我是编码新手,非常感谢任何建议。
  • @VittorioA。代码审查是所有专业人员用来检查代码的过程。这是其他开发人员阅读您的代码并指出的地方:1) 错误 2) 不良做法 3) 更好的技术 4) 可以使用的设计模式 5) 语言中使用的约定(习语)。
【解决方案2】:

所以我修改了相当多的代码。首先要注意的是我使用的是Node** 而不是Node* &amp;。在处理树和遍历算法时,这是一个非常常见的习惯用法。原因是您需要能够修改传入的指针(我认为这就是您使用Node* &amp; 的原因,您也可以这样做)。与insertIntoArray 的最大区别在于int i 变为int* i,这样每次调用insertIntoArray 可以共享相同的递增索引。我还添加了一点内存管理。

我还需要警告您,int arr[num]; 是一个可变长度数组 (VLA),不是标准 C++。 std::vector 是你应该走的路。 (事实上​​它使这个问题更容易,因为你可以很容易地追加)

#include <iostream>

using namespace std;

struct Node
{
    int label;
    Node* left;
    Node* right;

    ~Node() {
      delete left;
      delete right;
    }
};

void insertSearchNode(Node** tree, int x)       //insert integer x into the BST
{
    if (*tree) {
        if (x < (*tree)->label)
            insertSearchNode(&(*tree)->left, x);
        else
            insertSearchNode(&(*tree)->right, x);
    } else {
        *tree = new Node;
        (*tree)->label = x;
        (*tree)->right = NULL;
        (*tree)->left = NULL;
    }
}

void insertArrayTree(int arr[], int n, Node** tree)     //insert the array integer into the nodes label of BST
{
    for (int i = 0; i < n; i++)
        insertSearchNode(tree, arr[i]);
}

void insertIntoArray(int arr[], Node** tree, int* i)      //insert into the array the node label touched during an inorder tree traversal
{
    if (*tree) {
        if ((*tree)->left) insertIntoArray(arr, &(*tree)->left, i);
        arr[(*i)++] = (*tree)->label;
        if ((*tree)->right) insertIntoArray(arr, &(*tree)->right, i);
    }
}

int main()
{
    Node* maintree = NULL;

    int num;
    cin >> num;

    int arr[num];

    for (int i = 0; i < num; i++)    //initialize array with num-elements
        cin >> arr[i];

    insertArrayTree(arr, num, &maintree);    //insert elements into BST
    int index = 0;
    insertIntoArray(arr, &maintree, &index);  //modify array sorting his elements using the BST

    delete maintree;

    for (int y = 0; y < num; y++) 
        cout << arr[y] << ' ';
    cout << '\n';
}

【讨论】:

  • 非常感谢您的解决方案!所以基本上 Node** 和 Node*& 都可以正确使用吗?选择一个而不是另一个有什么好处?另外,为什么向量会使这个问题变得更容易?
  • 您无需创建运行索引即可插入向量。您可以在代码中使用双指针或指针引用来完成同样的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 2018-10-20
相关资源
最近更新 更多