前言:
分块分段进行分别的排序一直是一种很高效的的方式,至于为什么我之前一直不是很理解,知道接触到这个排序。奇列和偶咧并没有太大的关联,因此我们在现在普遍多核处理器的背景下(貌似已经八核了吧),可以极大地在硬件层面上提高效率,这是单线程排序所无法企及的。而且硬件还会不断的进步,在这种情况下,可以说多线程是必然的趋势。
思路:
奇偶排序,顾名思义,分类方法是吧数列关于下标分成奇数和偶数 ,这边有一个并不那么显而易见的问题就是,我们是否可以通过这种遍历方式遍历数列中的每一个数。这在遍历全体的排序中不是问题,然而在这种进行特殊种类分类的情况下却显得尤为重要。证明的话我不太懂,不过用笔试一试,可以发现是没有问题的。
那么,还有第二个问题,我们需不需要想希尔排序那样,每次都把奇列和偶列的全部元素排列有序呢?这里,针对这个Odd_EvenSort 他并没有这样的做,而是将每个数仅仅和他右边的数进行比较,确定这两个数的相对位置。像下标所演示的一样:
2 | 1 | 7 | 5 | 5 | 6 |
1 | 2 | 5 | 7 | 5 | 6 |
这个思路立马让我脑海里出现了那种滚动的感觉,在奇偶切换的过程中就像不断地将符合要求的滚到符合要求的位置一样,不知道大家是不是跟我有一样的感觉。
那么什么时候表示排序完成呢?这边需要借助一个指标:这一次排序没有进行交换,即完成了所有数的排序。
P.S 说是奇偶排序其实先进行奇排序还是偶排序没什么区别,可能仅仅是偶奇排序这个名字不好听罢了/doge。我们实现他就按名称实现好了:
void Odd_EvenSort(int *a,int length)
{
int i = 1;
int flag = 1;
while (flag)
{
flag = 0;
while (i < length - 1)//OddSort
{
if (a[i] > a[i + 1])
{
swap(&a[i],&a[i+1]);
flag = 1;
}
i += 2;//因为是奇列所以每次+2,下类似
}
i = 0;
while (i < length - 1)//EvenSort
{
if (a[i] > a[i + 1])
{
swap(&a[i], &a[i + 1]);
flag = 1;
}
i += 2;
}
i = 1;
}
}
这个排序很简单,但是还是需要注意一下这下标初始化以及变化的值的,我一开始就是这个点没有注意,然后调试了好多下。
测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 30
//之前写过了,就不再全写一遍了
void generate_random_number(int*, int, int);
void swap(int*, int*);
void Odd_EvenSort(int *a,int length)
{
int i = 1;
int flag = 1;
while (flag)
{
flag = 0;
while (i < length - 1)//OddSort
{
if (a[i] > a[i + 1])
{
swap(&a[i],&a[i+1]);
flag = 1;
}
i += 2;//因为是奇列所以每次+2,下类似
}
i = 0;
while (i < length - 1)//EvenSort
{
if (a[i] > a[i + 1])
{
swap(&a[i], &a[i + 1]);
flag = 1;
}
i += 2;
}
i = 1;
}
}
int main()
{
int arr[N + 10] = { 0 };
generate_random_number(arr, 0, 1024);
Odd_EvenSort(arr,N);
printf("排序后数列:\n");
for (int i = 0; i < N; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
排序结果:
至此,奇偶排序完成。