插入排序(直接插入排序,折半插入排序,2路插入排序,希尔排序)

/*
插入排序:直接插入排序,折半插入排序,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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值