排序数组,使所有正数首先出现

时间:2013-01-06 04:29:47

标签: c# arrays sorting

我在c#中编写一个代码来对数组进行排序,我希望右侧的所有负值和左侧的所有正值都不应该按降序排列

namespace SortApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
            int size = 12, i= 0;             // or newInt.Length

            for (i = 0; i < newInt.Length; i++)
            {
                if (newInt[i] < 0 && newInt[size] > 0)
                {
                    int temp = newInt[i];
                    newInt[i] = newInt[size];
                    newInt[size] = temp;
                    size--;
                }
            }
            for (i = 0; i < newInt.Length; i++)
            {
                Console.Write(newInt[i]);
                Console.Write(" ");
            }
        }
    }
}

但输出是这样的(-20是错误的一面):

5 10 9 8 -20 6 7 -14 15 -16 -4 -1 -2

但预期的输出是:

5 10 9 8 15 6 7 -14 -20 -16 -4 -1 -2 

为什么我的代码没有产生我想要的输出?

5 个答案:

答案 0 :(得分:5)

您的解决方案错误地决定何时完成循环。此外,它无条件地在循环标题中递增i,并且即使它指向负数也不会递减size

以下是解决问题的方法:

for (i = 0; i < size ; ) {
    if (newInt[i] < 0 && newInt[size] >= 0) {
        int temp = newInt[i];
        newInt[i] = newInt[size];
        newInt[size] = temp;
        size--;
        i++;
        continue;
    }
    if (newInt[i] >= 0) {
        i++;
    }
    if (newInt[size] < 0) {
        size--;
    }
}

这是demo on ideone

您可以使用leftright指针的更易读的标识符重写此循环,而不是使用isize。这将使您的算法在代码中看起来更“对称”,以识别其设计中的对称性:

int left = 0, right = newInt.Length-1;
while (left < right) {
    if (newInt[left] < 0 && newInt[right] >= 0) {
        int temp = newInt[left];
        newInt[left] = newInt[right];
        newInt[right] = temp;
        right--;
        left++;
        continue;
    }
    if (newInt[left] >= 0) {
        left++;
    }
    if (newInt[right] < 0) {
        right--;
    }
}

这是an ideone link to the alternative implementation

答案 1 :(得分:3)

试试这个解决方案:

var newInt = new[] {5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10};
var solution = newInt.GroupBy(i => i > 0).
    SelectMany(g => g).
    ToArray();

您的算法存在的问题是,当您减少size时,最终会将newInt[size]指向负值,并且不会输入if块。

答案 2 :(得分:1)

一个非常简单的解决方案的一般想法是启动一个索引,在数组的开头调用它left,在数组的末尾调用另一个索引right。 / p>

增加left,直到找到负数,或直到left == right。当您点击一个负数时,递减right直到找到正数,或直到right == left

如果left正在为负数编制索引而right正在为正数编制索引,则交换这两项并再次开始递增left

一般的想法,未经测试:

int left = 0;
int right = a.Length-1;
while (left < right)
{
    if (a[left] < 0)
    {
        while (right > left)
        {
            if (a[right] >= 0)
            {
                // swap here
                int temp = a[left];
                a[left] = a[right];
                a[right] = temp;
                break;
             }
             --right;
        }
    }
    ++left;
}

答案 3 :(得分:1)

这产生了具有最小循环的期望顺序

int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
int lt = 0;
int rt = newInt.Length - 1;
while (true) {
    // Find first negative number
    while (newInt[lt] >= 0 && lt < rt) {
        lt++;
    }

    // Find last positive number
    while (newInt[rt] < 0 && rt > lt) {
        rt--;
    }

    if (lt == rt) {
        break; // Finished
    }

    // Swap
    int temp = newInt[lt];
    newInt[lt] = newInt[rt];
    newInt[rt] = temp;
}
//TODO: Print result

答案 4 :(得分:0)

如果您可以使用泛型和linq而不是最简单的解决方案:

int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
newInt.ToList().Sort();
newInt.Reverse();
newInt = newInt.ToArray();

希望这会有所帮助!!