简体   繁体   English

仅对数组中的奇数或偶数进行排序

[英]Sort only either odd or even numbers from an array

I need to sort either the odd or even numbers in an array while leaving the rest unchanged. 我需要对数组中的奇数或偶数进行排序,而其余部分保持不变。 As this is part of a memory management course, I would strongly prefer not to duplicate any data so I didn't go for the obvious solution. 由于这是内存管理课程的一部分,因此我强烈希望不要重复任何数据,因此我不打算采用显而易见的解决方案。

I thought about using a simple bubble sort function by skipping the "bad" first or second params of the comparison. 我考虑过通过跳过比较的“错误”第一或第二个参数来使用简单的冒泡排序功能。 I will post the function only as the rest is irrelevant. 我将仅在其余部分无关时发布该函数。

//these are passed as sort_type_remainder
#define REMAINDER_EVEN 0
#define REMAINDER_ODD 1

void sort_integers(int *integer_list, int num_integers, int sort_type_remainder)
{
    int i, j, aux, offset = 1;
    for(i = 0; i < num_integers - 1; i++)
    {
        offset = 1;
        for(j = 0; j + offset < num_integers - i; j++)
        {
            if(abs(integer_list[j] % 2) != sort_type_remainder) //first element to be compared is of wrong type, skip
            {
                j++;
            }
            else
            {
                //first element is of good type, but second element is not, increase offset and reloop first element
                if(abs(integer_list[j + offset] % 2) != sort_type_remainder)
                {
                    j--;
                    offset++;
                }
                else //both elements are of good type, bubble sort them
                {
                    if(integer_list[j] > integer_list[j + offset])
                    {
                        aux = integer_list[j + offset];
                        integer_list[j + offset] = integer_list[j];
                        integer_list[j] = aux;
                    }
                    offset = 1;
                }
            }
        }
    }
}

This kind of works but some inputs are not processed properly and I can not figure out why. 这种工作,但某些输入未正确处理,我不知道为什么。 I tried reducing the input size to get a simpler way to reproduce this but as soon as I do so it starts working properly. 我尝试减小输入大小,以获得更简单的方式来重现此内容,但是一旦这样做,它便开始正常工作。

Here is the input / output, I deleted the even numbers as they stay in their position and it makes the error easier to notice. 这是输入/输出,我删除了偶数,因为它们保持在原位,这使错误更容易发现。

odd
20
13 5 -3 4 2 -7 23 -33 1 6 -8 7 10 -51 9 -5 12 92 69 55

产量

Any help or suggestions would be greatly appreciated, preferably with an explanation not just a solution. 任何帮助或建议,将不胜感激,最好是带说明而不仅仅是解决方案。

Edit:: full program is here, don't want to clutter the question http://pastebin.com/vZDcmppV 编辑::完整的程序在这里,不想让这个问题杂乱无章http://pastebin.com/vZDcmppV

What's wanted 想要什么

Given the description and the input data: 给定描述和输入数据:

  13   5  -3   4   2  -7  23 -33   1   6  -8   7  10 -51   9  -5  12  92  69  55

I believe that the requirement to sort the odd numbers into ascending order leaving the even numbers unmoved requires the output: 我相信将奇数按升序排序而使偶数保持不变的要求需要输出:

 -51 -33  -7   4   2  -5  -3   1   5   6  -8   7  10   9  13  23  12  92  55  69

And to sort the even numbers into ascending order leaving the odd numbers unmoved requires the output: 要将偶数按升序排序而不使奇数保持不变,需要输出:

  13   5  -3  -8   2  -7  23 -33   1   4   6   7  10 -51   9  -5  12  92  69  55

Concept behind the algorithm 算法背后的概念

One way to do this is to create an array of indices of the positions to be sorted: 一种方法是创建要排序的位置的索引数组:

int O = 13; // for sorting odd:
int opos[] = { 0,  1,  2,  5,  6,  7,  8, 11, 13, 14, 15, 18, 19 };

int E =  7; // for sorting even:
int epos[] = {  3,  4,  9, 10, 12, 16, 17 };

Then any sorting algorithm that would normally scan for (i = 0; i < N; i++) and then references A[i] would instead scan for (e = 0; e < E; e++) and reference A[epos[e]] . 然后,通常会扫描for (i = 0; i < N; i++)然后引用A[i]任何排序算法都将扫描for (e = 0; e < E; e++)和引用A[epos[e]]

So, we start with a simple-minded bubble sort that sorts a complete array A of type int with N elements: 因此,我们从一个简单的冒泡排序开始,该排序对具有N元素的int类型的完整数组A进行排序:

void bsort_1(int *A, int N)
{
     for (int i = 0; i < N - 1; i++)
     {
         for (int j = 0; j < N - 1 - i; j++)
         {
              if (A[j+1] < A[j])
              {
                  int t = A[j+1];
                  A[j+1] = A[j];
                  A[j] = t;
              }
         }
    }
}

Using O(N) auxilliary storage 使用O(N)辅助存储

We can adapt that to sort only the elements with a specified parity (0 for even, 1 for odd): 我们可以对其进行修改以仅对具有指定奇偶校验(0表示偶数,1表示奇数)的元素进行排序:

void bsort_4(int *A, int N, int parity)
{
    assert(parity == 0 || parity == 1);
    assert(N < 1024 * 1024);
    int posn[N];
    int count = 0;
    for (int i = 0; i < N; i++)
    {
        if ((A[i] & 1) == parity)
            posn[count++] = i;
    }
    if (count < 2)
        return;
    for (int i = 0; i < count - 1; i++)
    {
        for (int j = 0; j < count - 1 - i; j++)
        {
            if (A[posn[j + 1]] < A[posn[j]])
            {
                int t = A[posn[j + 1]];
                A[posn[j + 1]] = A[posn[j]];
                A[posn[j]] = t;
            }
        }
    }
}

This establishes the indexes that correspond to odd or even entries in the array, and then sorts just those elements of the array. 这将建立与数组中奇数或偶数条目相对应的索引,然后仅对数组中的那些元素进行排序。

Test code and results 测试代码和结果

That needs some test code to be reasonably confident it is doing what it is supposed to do. 这就需要一些测试代码来合理地确定它正在执行应做的事情。

#include <assert.h>
#include <stdio.h>

static void bsort_4(int *A, int N, int parity)
{
    assert(parity == 0 || parity == 1);
    assert(N < 1024 * 1024);
    int posn[N];
    int count = 0;
    for (int i = 0; i < N; i++)
    {
        if ((A[i] & 1) == parity)
            posn[count++] = i;
    }
    if (count < 2)
        return;
    for (int i = 0; i < count - 1; i++)
    {
        for (int j = 0; j < count - 1 - i; j++)
        {
            if (A[posn[j + 1]] < A[posn[j]])
            {
                int t = A[posn[j + 1]];
                A[posn[j + 1]] = A[posn[j]];
                A[posn[j]] = t;
            }
        }
    }
}

static void dump_array(const char *tag, const int *a, int n)
{
    printf("%-8s", tag);
    for (int i = 0; i < n; i++)
        printf(" %3d", a[i]);
    putchar('\n');
}

static void test_sorting(const int *data, int size, int parity)
{
    int array[size];
    for (int i = 0; i < size; i++)
        array[i] = data[i];
    dump_array("Before:", array, size);
    bsort_4(array, size, parity);
    dump_array("After:", array, size);
}

int main(void)
{
    const int array[] =
    {
        13,   5,  -3,   4,   2,  -7,  23, -33,   1,   6,
        -8,   7,  10, -51,   9,  -5,  12,  92,  69,  55,
    };
    enum { A_SIZE = sizeof(array) / sizeof(array[0]) };

    printf("Sort even numbers:\n");
    test_sorting(array, A_SIZE, 0);
    printf("Sort odd  numbers:\n");
    test_sorting(array, A_SIZE, 1);

    return 0;
}

Output: 输出:

Sort even numbers:
Before:   13   5  -3   4   2  -7  23 -33   1   6  -8   7  10 -51   9  -5  12  92  69  55
After:    13   5  -3  -8   2  -7  23 -33   1   4   6   7  10 -51   9  -5  12  92  69  55
Sort odd  numbers:
Before:   13   5  -3   4   2  -7  23 -33   1   6  -8   7  10 -51   9  -5  12  92  69  55
After:   -51 -33  -7   4   2  -5  -3   1   5   6  -8   7  10   9  13  23  12  92  55  69

You have to take my word for it that the required outputs were created before running any of the programs that I used to arrive at this final result. 您必须相信,在运行我用来获得最终结果的任何程序之前,已创建了必需的输出。

This code can be adapted to other sort strategies — insertion, selection, shell, merge, quick. 该代码可以适应其他排序策略-插入,选择,shell,合并,快速。 The scan that sets up the posn array is needed in the top-level operation (but should be avoided for recursive calls in sorts like merge sort and quick sort), and then the rest of the code uses the extra level of indirection. 在顶层操作中需要进行扫描以设置posn数组(但对于诸如归并排序和快速排序之类的递归调用,应避免扫描),然后其余代码使用额外的间接级别。

Avoiding O(N) auxilliary storage 避免O(N)辅助存储

If the extra array used isn't acceptable for some reason, then you have to go about things in a much more contorted way, and you get a larger runtime penalty because you have to calculate the elements of the posn array on the fly, rather than precomputing them once. 如果由于某种原因而不能使用额外的数组,那么您必须以一种更加扭曲的方式处理问题,并且会产生更大的运行时损失,因为您必须动态计算posn数组的元素,而不是而不是预先计算一次。 The comparisons in the sort are always between adjacent positions. 排序中的比较总是在相邻位置之间进行。 Without the posn array, the code still establishes the count of odd or even values, but there's be code to step through the data array to find the next value with the correct parity: 如果没有posn数组,代码仍会建立奇数或偶数值的计数,但是仍有一些代码可以逐步遍历数据数组以找到具有正确奇偶校验的下一个值:

#include <assert.h>
#include <stdio.h>

static void bsort_4(int *A, int N, int parity)
{
    assert(parity == 0 || parity == 1);
    assert(N < 1024 * 1024);
    int count = 0;
    for (int i = 0; i < N; i++)
    {
        if ((A[i] & 1) == parity)
            count++;
    }
    if (count < 2)
        return;
    for (int i = 0; i < count - 1; i++)
    {
        int i0 = 0;
        while ((A[i0] & 1) != parity)
            i0++;
        for (int i1 = 0; i1 < i; i1++)
        {
            while ((A[i0] & 1) != parity)
                i0++;
        }
        int j0 = i0;
        for (int j = 0; j < count - 1 - i; j++)
        {
            int j1 = j0 + 1;
            while ((A[j1] & 1) != parity)
                j1++;
            /*printf("P = %d; j0 = %2d; A[j0] = %3d; j1 = %2d; A[j1] = %3d\n",*/
            /*       parity, j0, A[j0], j1, A[j1]);*/
            if (A[j1] < A[j0])
            {
                int t = A[j1];
                A[j1] = A[j0];
                A[j0] = t;
            }
            j0 = j1;
        }
    }
}

static void dump_array(const char *tag, const int *a, int n)
{
    printf("%-8s", tag);
    for (int i = 0; i < n; i++)
        printf(" %3d", a[i]);
    putchar('\n');
}

static void test_sorting(const int *data, int size, int parity)
{
    int array[size];
    for (int i = 0; i < size; i++)
        array[i] = data[i];
    dump_array("Before:", array, size);
    bsort_4(array, size, parity);
    dump_array("After:", array, size);
}

int main(void)
{
    const int array[] =
    {
        13,   5,  -3,   4,   2,  -7,  23, -33,   1,   6,
        -8,   7,  10, -51,   9,  -5,  12,  92,  69,  55,
    };
    enum { A_SIZE = sizeof(array) / sizeof(array[0]) };

    printf("Sort even numbers:\n");
    test_sorting(array, A_SIZE, 0);
    printf("Sort odd  numbers:\n");
    test_sorting(array, A_SIZE, 1);

    return 0;
}

I'm not happy about the variable naming in bsort_5() , but I don't immediately have better names to use. 我对bsort_5()的变量命名bsort_5() ,但是我没有立即使用更好的名称。

Output: 输出:

Sort even numbers:
Before:   13   5  -3   4   2  -7  23 -33   1   6  -8   7  10 -51   9  -5  12  92  69  55
After:    13   5  -3  -8   2  -7  23 -33   1   4   6   7  10 -51   9  -5  12  92  69  55
Sort odd  numbers:
Before:   13   5  -3   4   2  -7  23 -33   1   6  -8   7  10 -51   9  -5  12  92  69  55
After:   -51 -33  -7   4   2  -5  -3   1   5   6  -8   7  10   9  13  23  12  92  55  69

Note that this relies on the fact that the bubble sort shown only compares adjacent entries of the same parity. 请注意,这取决于以下事实:显示的冒泡排序仅比较相同奇偶校验的相邻条目。 For sorts like shell, merge, quick sort which work on arbitrary positions, it is not appropriate — the loops to find the right indices would be appallingly expensive. 对于像shell,merge,快速排序这样可以在任意位置工作的排序,这是不合适的-查找正确索引的循环会非常昂贵。 You'd almost certainly be better off with the bubble sort (or maybe selection sort or insertion sort). 几乎可以肯定,冒泡排序(或者选择排序或插入排序)会更好。

GitHub GitHub上

This code is available in my SOQ (Stack Overflow Questions) repository on GitHub as files bsort1.c , bsort4.c and bsort5.c in the src/so-4295-4541 sub-directory. 该代码在GitHub上的我的SOQ (堆栈溢出问题)存储库中以src / so-4295-4541子目录中的文件bsort1.cbsort4.cbsort5.c 可用

If you need to sort either odd or even numbers from an array, this is my method: 如果您需要对数组中的奇数或偶数进行排序,这是我的方法:

I would first of all pick from the starting array all odd or even numbers depending and what you want to do, replace everything by an indicator (1 or 2 depends if you want to sort odds or evens). 我首先要从起始数组中选择所有奇数或偶数,具体取决于您想要做什么,用指示符替换所有内容(1或2取决于您是否要对偶数或偶数进行排序)。

Then sort the array by itself (if you want to use another algorithm than the bubble sort, there's Big-o cheat sheet , very useful). 然后对数组本身进行排序(如果您想使用除冒泡排序之外的其他算法, 可以使用Big-o备忘单 ,非常有用)。

And then you just scan your first array by replacing every indice by every sorted numbers depending on their position. 然后,您只需扫描第一个数组,即可根据位置将每个索引替换为每个已排序的数字。

In short : 简而言之 :

You want to put every odd (or even) number from array 1 into array 2, and replace them by an indicator (anything you might recognize when scaning array 1 after). 您想将数组1中的每个奇数(或偶数)放入数组2中,并用指示符替换它们(之后扫描数组1时可能会识别的任何内容)。

You want to sort array 2. 您想对数组2进行排序。

Then you want to replace every indicator by every element from array 2. 然后,您要用数组2中的每个元素替换每个指标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何仅返回具有偶数/奇数的数组并删除不必要的单元格? - How to return array with only even/odd numbers and delete the unnecessary cells? 在数组中配对偶数和奇数 - Pairing even and odd numbers in an array 分配偶数和奇数的数组 - An array to assign even and odd numbers 按出现的顺序对奇数和偶数进行排序 - Sort odd and even numbers in the same order that they appear 给定一个由偶数和奇数组成的数组。 先对偶排序,然后对偶排序。 数字的顺序不能更改 - Given an array consisting of even and odd numbers. Sort the array with even first and then odds. The order of numbers can't be changed 冒泡排序,但仅对偶数放置的数字进行排序,并在 c 中留下奇数放置的元素 - Bubble sort, but sorting only even placed numbers ascending and leaving odd placed elements in c 在C中的数组内交换奇数和偶数 - swapping odd and even numbers inside an Array in C 在数组中交换奇数和偶数,C - swap odd and even numbers inside an Array, C 编写C程序以将数组中的数字排列为一系列奇数和偶数 - Write a C program to arrange the numbers in an array as a series of odd and even numbers 编写一个 C 程序,从给定的整数数组创建新数组,将所有偶数移到所有奇数之前 - Write a C program to create new array from a given array of integers shifting all even numbers before all odd numbers
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM