算法问题的一个分类:排高低。
背景:有一系列的值,有大有小,由于某个目的(比如两两分组让最小者的和最大、比如容纳最多和不超过某个值的元素、等等),需要先把它们排一下高低。
一个数值数组,怎么给里面的元素排出高低(比如由小到大地排序)?
两两比较不是问题,要解决的是这两个问题:
* 谁跟谁比,怎么安排?
* 比后怎么处置,怎么让问题变小?
全由你来设计!
设计原则:让问题变小,最终没有。
不能随意地比较,比如安排单数的元素来比较,这个设计看不出能解决问题。
不能比完之后却没有进一步的动作,只比较却不记录也不作换位之类,明显没有意义。
谁来比,以及比后怎么处置,不同的安排,产生不同的算法。
为了简化思考,可以只考虑只有两个元素的情况。
比如:
* 让n1跟n2比较,如果n1>n2,则值互换位置,让n1最小。然后,继续让n1与n3比较,同样最小的放到n1”。全部比较完后,第一个位置就是最小的,之后再同样考虑第二个位置(问题规模在收敛)。这是“冒泡排序”算法。
* 让n1跟最后一个比较,再跟倒数第二个比较,…,小的放到n1。再考虑n2…。这是“冒泡排序”算法。
* 让n1跟n2比,n2跟n3比…,大者放到后面。一轮下来,最后的位置就是最大值,然后放过这个位置再重复。这是“冒泡排序”算法。
* 模拟排队(从一个都没有开始),从左往右,找到一个比自己高的元素,排到前面。这是“插入排序”。
* 第一个跟最后一个比较,第二个跟倒数第二个比较,…,小的放到左边,大的放到右边。这是“快速排序”的初型。
注意,“谁来比”不要有遗漏,否则不公平。
以上,更多想说明,你可以自己设计,并不一定要从已知的算法去思考。同时也说明了,冒泡排序、插入排序的思路以及快速排序的初型。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bubble1(int* arr, int size) {
for (int i = 0; i < size-1; i ++) {
for (int j = i+1; j < size; j ++) {
if (arr[i] > arr[j]) {
arr[i]=arr[i] ^ arr[j];
arr[j]=arr[i] ^ arr[j];
arr[i]=arr[i] ^ arr[j];
}
}
}
}
void bubble2(int* arr, int size) {
for (int i = 0; i < size-1; i ++) {
for (int j = size-1; j > i; j --) {
if (arr[i] > arr[j]) {
arr[i]=arr[i] ^ arr[j];
arr[j]=arr[i] ^ arr[j];
arr[i]=arr[i] ^ arr[j];
}
}
}
}
void bubble3(int* arr, int size) {
int count = size;
while (count) {
for (int i = 0; i < count-1; i ++) {
if (arr[i] > arr[i+1]) {
arr[i]=arr[i] ^ arr[i+1];
arr[i+1]=arr[i] ^ arr[i+1];
arr[i]=arr[i] ^ arr[i+1];
}
}
count --;
}
}
// 多用一个临时组
void insertsort(int* arr, int size) {
int* tmparr=(int*)malloc(sizeof(int) * size);
memcpy(tmparr, arr, size*sizeof(int));
int count = 0;
for (int i = 0; i < size; i ++) {
int j=0;
for (j = 0; j < count; j ++) {
if (arr[i]<tmparr[j]) {
memcpy(tmparr+j+1, tmparr+j, (size-j-1)*sizeof(int));
tmparr[j]=arr[i];
break;
}
}
if (j==count) {
tmparr[j]=arr[i];
}
count ++;
}
memcpy(arr, tmparr, size*sizeof(int));
free(tmparr);
}
// 就地insert
void insertsort2(int* arr, int size) {
for (int i = 0; i < size; i ++) {
for (int j = 0; j < i; j ++) {
if (arr[i] < arr[j]) {
int t = arr[i];
memcpy(arr+j+1, arr+j, (i-j)*sizeof(int));
arr[j]=t;
break;
}
}
}
}
int main(int argc, char *argv[])
{
int arr[] = {5, 3, 6, 1, 2};
int size = sizeof arr/sizeof *arr;
/*bubble3(arr, size);*/
insertsort2(arr, size);
for (int i = 0; i < size; i ++) {
printf("%d, ", arr[i]);
}
return 0;
}