/*
插入排序:直接插入排序,折半插入排序,2路插入排序,希尔排序
将数据由小到大排列
运行环境:VS2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 1
#define ERROR 0
#define MAXSIZE 50
typedef struct
{
int value;
}RedType;
typedef struct
{
RedType red[MAXSIZE+1]; //red[0]用作哨兵单元
int length;
}SqList;
SqList *CreateSqList()
{
int i = 0;
int j = 0;
char buf[4*MAXSIZE] = "";
char *ptr = NULL;
SqList *sqlist = (SqList *)malloc(sizeof(SqList));
memset(sqlist, 0, sizeof(SqList));
printf("请输入待排序数据,以逗号分隔,以分号结束\n"
"例:23,12,65,36,35;\n"
"input:");
scanf("%s", buf);
ptr = buf;
sqlist->red[i].value = 0; //red[0]不存值用作哨兵单元
i = 1;
while(*ptr != ';')
{
sqlist->red[i].value = atoi(ptr);
i++;
ptr = strstr(ptr, ",");
if(!ptr)
{
break;
}
ptr++;
}
sqlist->length = (i - 1);
return sqlist;
}
//直接插入排序
int StraightInsertSort(SqList *sqlist)
{
int i = 0;
int j = 0;
for(i = 2; i <= sqlist->length; i++)
{
if(sqlist->red[i].value < sqlist->red[i-1].value)
{
sqlist->red[0] = sqlist->red[i];
sqlist->red[i] = sqlist->red[i-1];
for(j = (i - 2); (sqlist->red[0].value < sqlist->red[j].value); j--)
{
sqlist->red[j+1] = sqlist->red[j]; //大于哨兵位置的记录后移
}
sqlist->red[j+1] = sqlist->red[0]; //将哨兵处的数据插入到正确位置
}
}
return OK;
}
//折半插入排序
int BinaryInsertSort(SqList *sqlist)
{
int i = 0;
int j = 0;
int low = 0;
int high = 0;
int mid = 0;
for(i = 2; i <= sqlist->length; i++)
{
sqlist->red[0] = sqlist->red[i];
low = 1;
high = i-1;
while(low <= high)
{
mid = (high + low) / 2;
if(sqlist->red[0].value < sqlist->red[mid].value)
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
for(j = i - 1; j > high; j--)
{
sqlist->red[j+1] = sqlist->red[j];
}
sqlist->red[j+1] = sqlist->red[0];
}
return OK;
}
//2路插入排序
int P2InsertSort(SqList *sqlist)
{
int i = 0;
int j = 0;
int first = 0; //记录排好序的那段数据的第一个位置,即最小值所在位置
int final = 0; //记录排好序的那段数据的最后一个位置,即最大值所在位置
RedType *d = NULL;
d = (RedType *)malloc(sqlist->length * sizeof(RedType));
memset(d, 0, sqlist->length * sizeof(RedType));
d[0].value = sqlist->red[1].value;
first = 0;
final = 0;
for(i = 2; i <= sqlist->length; i++)
{
if(sqlist->red[i].value > d[final].value) //sqlist->red[i]的值比当前有序数组最大值还大
{
final = final + 1;
d[final] = sqlist->red[i];
}
else if(sqlist->red[i].value < d[first].value) //sqlist->red[i]的值比当前有序数组最小值还小
{
first = (first - 1 + sqlist->length) % sqlist->length;
d[first] = sqlist->red[i];
}
else //插入到d[]的中间,需要移动d
{
j = final;
sqlist->red[0] = sqlist->red[i];
while(d[j].value > sqlist->red[0].value)
{
d[(j + 1) % sqlist->length] = d[j];
j = (j - 1 + sqlist->length) % sqlist->length;
}
d[(j + 1) % sqlist->length] = sqlist->red[0];
final = final + 1; //别忘了final+1,因为添了一个数据,一部分数据都向后移了一个单位
}
}
//最后把d[]中的值放到sqlist->red[]中
j = first;
for(i = 1; i <= sqlist->length; i++)
{
sqlist->red[i] = d[j];
j = (j + 1) % sqlist->length;
}
free(d);
return OK;
}
//一趟希尔排序
int ShellInsert(SqList *sqlist, int dk)
{
int i = 0;
int j = 0;
for(i = (dk + 1); i <= sqlist->length; i++)
{
if(sqlist->red[i].value < sqlist->red[i-dk].value)
{
sqlist->red[0] = sqlist->red[i]; //暂存在sqlist->red[0]中
for(j = (i - dk); ((j > 0) && (sqlist->red[0].value < sqlist->red[j].value)); j = (j - dk))
{
sqlist->red[j+dk] = sqlist->red[j]; //记录后移,查找插入位置
}
sqlist->red[j+dk] = sqlist->red[0];
}
}
return OK;
}
/*
功能:希尔排序
参数: sqlist 待排序的数组
dlta 记录增量的数组
t 增量数组的长度
*/
int ShellSort(SqList *sqlist,int dlta[],int t)
{
int k;
for(k = 0; k < t; k++)
{
// 一趟增量为dlta[k]的插入排序
ShellInsert(sqlist, dlta[k]);
}
return OK;
}
//打印表中数据
int PrintSqList(SqList sqlist)
{
int i = 0;
for(i = 1; i <= sqlist.length; i++)
{
printf("%d,", sqlist.red[i].value);
}
printf("\b;\n");
return OK;
}
int main()
{
SqList *sqlist = NULL;
SqList *testSqList = NULL;
int dt[3] = {5,3,1}; //希尔排序中的增量数组
sqlist = CreateSqList();
testSqList = (SqList *)malloc(sizeof(SqList));
printf("\n直接插入排序:\n");
memcpy(testSqList, sqlist, sizeof(SqList));
PrintSqList(*testSqList);
StraightInsertSort(testSqList);
PrintSqList(*testSqList);
printf("\n折半插入排序:\n");
memcpy(testSqList, sqlist, sizeof(SqList));
PrintSqList(*testSqList);
BinaryInsertSort(testSqList);
PrintSqList(*testSqList);
printf("\n2路插入排序:\n");
memcpy(testSqList, sqlist, sizeof(SqList));
PrintSqList(*testSqList);
P2InsertSort(testSqList);
PrintSqList(*testSqList);
printf("\n希尔排序:\n");
memcpy(testSqList, sqlist, sizeof(SqList));
PrintSqList(*testSqList);
ShellSort(testSqList, dt, 3);
PrintSqList(*testSqList);
free(testSqList);
free(sqlist);
system("pause");
return 0;
}