将元素插入到已排序的数组中

时间:2017-05-23 11:59:52

标签: c++ arrays

我需要做的是从数组的后面开始工作(我必须使用动态数组)。填充数组时,我需要检查如果我想插入的元素小于当前元素,我必须移动这些元素以创建一个“洞”。

假设我有一个看起来像这样的数组:

index:    0   |   1   |   2   |   3   |   4
value:    10  |   11  |   13  |   14  |   NULL

在我当前的代码中,数组大小始终比当前大小大1。所以在上面,数组的大小将是5.这允许转移。

现在假设我需要将元素12插入数组中。所以我需要从位置4x[3]开始,其值为14

我目前有以下内容:

// theSize is a private member of a class that holds the array
int j = theSize - 1;
// dynamic allocation
int *temp = new int[theSize];
for (int k = 0; k < theSize; k++) {
    temp[k] = x[k];
}
delete [] x;
// using j >=0 because I need to check as low as the x[0] value
for(; j >=0 && element < temp[j]; --j) {
    // So in the first run starting at x[3]
    //    this would be the value at x[3] is now at x[4]
    temp[j] = temp[j+1];
}

temp[j] = element;
x = temp;
delete [] temp;
theSize++

因此,例如,在第一次运行之后,数组将如下所示:

index:    0   |   1   |   2   |   3   |   4
value:    10  |   11  |   13  |       |   14

我看到很多从后面移过阵列但更改的例子:

x[j] = x[j+1]x[j] = x[j-1]

我不确定你为什么要x[j-1],因为左边是1值,我想向右移动。

我对数组索引的理解是否需要更正?

TL:DR 我遇到的问题是,有时候,当比较element < temp[j]时,布尔值返回的值不小于实际值。我已经通过了一个调试器,正在比较正确的值,但它让我想知道它是否从一个旧的数组索引中提取一个值。

4 个答案:

答案 0 :(得分:1)

您的代码似乎有问题(您有一个new[]但只有两个delete[],您认为这可以起作用吗?)

int *temp = new int[theSize];
/* ... */
x = temp;
delete [] temp;       // delete memory pointed to by x

你只需删除动态分配的数组,使x成为悬空指针。我很惊讶你没有得到分段错误。只需删除delete[] temp;

即可

此外,无需先将所有数据复制到临时数组,然后再进行随机播放。你只需一次扫描即可完成所有工作:

int k = Size;             // Size is the actual size, not one larger
int*temp = new int[Size+1];
for(; k && element < x[k-1]; --k)
  temp[k] = x[k-1];
temp[k] = element;
for(; k; --k)
  temp[k-1] = x[k-1];
delete[] x;
x = temp;
++Size;

答案 1 :(得分:1)

两件事:

首先,在释放x = temp后分配temp时,代码会产生内存泄漏和未定义的行为。

其次,我将用于查找元素的代码与用于移动数组中元素的代码分开,而不是单独复制一个值。对于复制元素,您可以使用std::copy_nstd::copy_backward(如果源和目标范围重叠)。找到&#34;最近的&#34;值,您可以使用std::lower_bound。请参阅以下代码,使您的程序适应这些功能的使用:

int main() {

    int *x = new int[4] { 10  ,   11  ,   13  ,   14 };
    int theSize = 4;

    int *temp = new int[theSize+1];
    std:copy_n(x, theSize, temp);
    int* f = std::lower_bound(temp,temp+theSize,12);
    std::copy_backward(f,temp+theSize,temp+theSize+1);
    *f = 12;
    delete[] x;
    x = temp;
    theSize++;

    return 0;
}

答案 2 :(得分:0)

原样使用std::setKISS

#include <iostream>
#include <set>
using namespace std;

int main() {
    std::set<int> x={10,11,13,14};
    x.insert(12);


    for (const int& i : x) // access by const reference
        std::cout << i << ' ';
    std::cout << '\n';
    return 0;
}

Live Example!

结果:

  

10 11 12 13 14

注意:
这使得您在x中存储的数据可以进行排序和唯一,如果您希望可以将其更改为std::multiset(与set不同,允许使用具有等效值的多个键)。

答案 3 :(得分:-1)

没有足够的代表发表评论,经过很长一段时间的潜伏终于成了账号。我将研究使用双向链表,迭代列表并在设置位置注入变量更容易。例如,您可以使用header.back引用第一个和最后一个项目,最后一个项目将其视为一个圆圈,h​​eader.next将引用第一个项目,具体取决于您如何定义标题。您可以根据自己的用例操作链接列表,因为每个项目都引用了之前和之后的项目。如果这听起来有益,我可以挖掘一些项目作为一个可靠的例子。