在跳过值时排序数组

时间:2013-06-16 23:57:37

标签: c arrays sorting

我有这个一维数组:

0, 0, 2, 0, 0, 0, 1, 7, 4, 0

我需要能够在C中对这个数组进行排序,其排序算法比冒泡排序更有效,比如插入排序。我还需要在不创建新数组的情况下对其进行排序。但是,我需要忽略0。

示例排序数组将是:

0, 0, 1, 0, 0, 0, 2, 4, 7, 0

3 个答案:

答案 0 :(得分:3)

您运行与插入排序运行相同的算法,但实际移动值时,跳过零。

所以举个例子:

0, 0, 2, 0, 0, 0, 1, 7, 4, 0

假设没有零:2, 1, 7, 4。您阅读1,将其与之前的值(2)进行比较,然后将2移到1所在的位置:

2, 1*, 7, 4 (copy 1 to register, shift the 2 since it is bigger than 1)
2, 2*, 7, 4 (write the 1 in that place)
1, 2*, 7, 4 (since there are no previous elements we are done)

在该迭代结束时,星号前的所有内容都已排序。

现在与零的区别在于您需要跟踪“上一个”和“当前”位置(<>

0, 0, 2, 0, 0<, 1*> (copy 1 to register, compare to value at `<`)
0, 0, 2, 0<, 0, 1*> (Since it is zero, move the previous head further back)
0, 0, 2<, 0, 0, 1*> (Since it is zero, move the previous head further back)
0, 0, 2<, 0, 0, 2*> (Check if 1 < 2.  Since it is, write the 2 in the current head)
0, 0, 2<>, 0, 0, 2*  (move the current head)
0, 0<, 2>, 0, 0, 2*  (move the previous head back)
0<, 0, 2>, 0, 0, 2*  (move the previous head back)
0<, 0, 1>, 0, 0, 2*  (Since we hit the front, we know that we have to write the `1` in the place marked by the "current" position)

如果您没有达到目的,请考虑0, 1, 0, 3, 0, 2, 0。第六次迭代中的步骤是

0, 1, 0, 3, 0, 2*<>, 0
....
0, 1<, 0, 3>, 0, 3*, 0 (do the comparison and see that 1 < 2 but 2 < 3, so we want to write the 2 here and end this iteration)

0, 1<, 0, 2>, 0, 3*, 0 (now we know the elements before the * are sorted, so we can move on)

答案 1 :(得分:0)

修改快速排序算法,以便:

  • 当您决定项目是否在枢轴的左侧或右侧时,它保持不变0

  • 确保您没有选择0作为枢轴值。因此,随机qsort可能是更好的选择

  • 如果[递归]输入数组全部为零,请确保返回

例如,从the Rosetta code修改:

void quick_sort (int *a, int n) {
    if (n < 2) return;

    // don't sort all-zero sub-arrays:
    int c = 0,i;
    for (i=0; i < n; i++) { c += a[i]; }
    if (!c) return;

    // don't choose 0 as the pivot value:
    int p;
    do {
       p = a[rand()%n];
    } while (p == 0); 

    int *l = a;
    int *r = a + n - 1;

    // make sure not to move zeros:
    while (l[0] == 0 || l <= r) {
        if (*l < p) {
            l++;
            continue;
        }   
        if (r[0] == 0 || *r > p) {
            r--;
            continue; 
        }   
        int t = *l; 
        *l++ = *r; 
        *r-- = t;
    }   
    quick_sort(a, r - a + 1); 
    quick_sort(l, a + n - l); 
}

答案 2 :(得分:-1)

首先,从观察开始,当您将域限制为整数时,只有一个零。要忽略的值不需要留在内存中。否则,如果你排序的不是整数,而是按第一个坐标排序的整数对,那么会有很多零(<0,0><0,1>,...),你必须以某种方式存储它们

在这种情况下,您可以将所有非零数字移动到数组的开头,将它们移动到最初包含零的点;在这样做时,记录零在数组末尾的索引。

此时,您可以对数组的开头进行排序,然后按零顺序交错值,就像在数组末尾有适当的索引一样。