#include <stdio.h>
#define MAXSIZE 200
/* 冒泡排序
* 选择排序
* 插入排序
* 快速排序
* 希尔排序
* 折半插入排序
*/
typedef struct _node {
int elem[MAXSIZE+1];
int length; // length = MAXSIZE
} node;
/* 冒泡排序 */
node *bubblesort(node *L) // 排序后单调不减
{
int i, j, flag;
node *head;
for (i=1; i<L->length; i++) // 最坏n-1趟
{
flag = 0;
for (j=1; j<L->length-i+1; j++) // 记住: 一个for就可以解决一趟冒泡. :-)
if (L->elem[j] > L->elem[j+1])
{
flag = 1;
L->elem[0] = L->elem[j];
L->elem[j] = L->elem[j+1];
L->elem[j+1] = L->elem[0];
}
if (flag == 0) // 判断有序依据
break;
}
return (head);
}
/* 选择排序 */
node *selectsort(node *L) // 排序后单调不增
{
node *head = L;
int i, j, k;
for (i=1; i<L->length; i++) // n-1趟
{
L->elem[0] = L->elem[i];
k = i; // not forget!
for (j=i+1; j<=L->length; j++) // 从头到尾依次排好.
if (L->elem[j] > L->elem[0])
{
L->elem[0] = L->elem[j];
k = j;
}
if (k != i)
{
L->elem[0] = L->elem[k];
L->elem[k] = L->elem[i];
L->elem[i] = L->elem[0];
}
}
return (head);
}
/* 插入排序 */
node *insertsort(node *L) // 排序后单调不减
{
node *head = L;
int i, j;
for (i=2; i<=L->length; i++)
if (L->elem[i-1] > L->elem[i])
{
L->elem[0] = L->elem[i];
L->elem[i] = L->elem[i-1];
for (j=i-2; L->elem[j] > L->elem[0]; j--) // 考虑2个元素且相等情形, 较易理解.
L->elem[j+1] = L->elem[j];
L->elem[j+1] = L->elem[0];
}
return (head);
}
int partition(node *L, int low, int high) // 按枢轴shu1进行划分, 并返回最终枢轴的位置信息.
{
L->elem[0] = L->elem[low];
while (low < high)
{
while (low < high && L->elem[high] <= L->elem[0])
high--;
L->elem[low] = L->elem[high]; // 算法每次的赋值过程,实际上可以抽象为空出一格来.
while (low < high && L->elem[low] >= L->elem[0])
low++;
L->elem[high] = L->elem[low];
}
L->elem[low] = L->elem[0]; // 此时只要经过了上面的大while,则low = high.
return low;
}
void qsort(node *L, int low, int high)
{
int pivotloc;
if (low < high) // 不是 while
{
pivotloc = partition(L, low, high);
qsort(L, low, pivotloc-1);
qsort(L, pivotloc+1, high);
}
return ;
}
/* 快速排序 */
node *quicksort(node *L) // 排序后单调不增
{ // 关键点: 1. 按枢纽点分区; 2. 递归(包括不断分区).
node *head = L;
qsort(L, 1, L->length);
return (head);
}
/* 希尔排序 */
node *shellsort(node *L) // 排序后单调不减
{
node *head = L;
int i, j;
int dk = (L->length+2)/2; // decided by use case, 如果不同dk有公因子,也能完成排序, 影响的只是时间复杂度.
while (dk>0)
{
for (i=dk+1; i<=L->length; i++) // dk = 1时,是直接插入排序法, 保证有dk = 1情形,就可以保证排序成功.
if (L->elem[i] < L->elem[i-dk])
{
L->elem[0] = L->elem[i];
j = i - dk;
while (j>0 && L->elem[0]<L->elem[j])
{
L->elem[j+dk] = L->elem[j];
j = j - dk;
}
L->elem[j+dk] = L->elem[0];
}
dk = dk/2;
}
return (head);
}
/* 折半插入排序 */
node *binaryinsertsort(node *L) // 排序后单调不增
{
node *head = L;
int i, j, low, high, mid;
for (i=2; i<=L->length; i++)
{
low = 1; high = i-1; // i-1
L->elem[0] = L->elem[i]; // elem[i] 是待插入的元素.
while (low <= high)
{
mid = (low+high)/2;
if (L->elem[mid] > L->elem[0]) // elem[mid] 和 elem[0] 比较.
high = mid - 1;
else
low = mid + 1; // 将EQ的结果放在这里,是为了得到high值,可以验证.
}
for (j = i; j>high+1; j--) // not ">=";
L->elem[j] = L->elem[j-1];
L->elem[high+1] = L->elem[0];
}
// so ugly, for符合单调不增, 而不改动上面的主体.
int t[L->length+1];
for (i=L->length; i>0; i--)
t[L->length-i+1] = L->elem[i];
for (i=1; i<=L->length; i++)
L->elem[i] = t[i];
return (head);
}
void kprint(node *L)
{
static int count = 1;
printf("Print times: %d/n", count);
int i;
for (i=0; i<L->length; i++)
printf("%2d ", L->elem[i+1]);
printf("/n/n");
count++;
return ;
}
int main()
{
int i;
node mytest;
mytest.length = MAXSIZE;
for (i=1; i<=MAXSIZE; i++)
mytest.elem[i] = MAXSIZE - i + 1;
kprint(&mytest);
bubblesort(&mytest);
kprint(&mytest);
selectsort(&mytest);
kprint(&mytest);
insertsort(&mytest);
kprint(&mytest);
quicksort(&mytest);
kprint(&mytest);
shellsort(&mytest);
kprint(&mytest);
binaryinsertsort(&mytest);
kprint(&mytest);
return 0;
}