C语言的排序算法(冒泡,选择,插入,Hash,快速排序)

算法的稳定性,我自己概括为:在一次排序过程中,如果出现两个相同的值,这两个相同值的相对位置不发生变化,那么他就是稳定的。比如一个数组a[5] = {1,4,3,4,1},对于这个数组,他排完序后第一个‘4’和第二个‘4’的相对位置不发生变化,就是稳定的。

首先定义一个数组,我定义是赋初值的,当然也可以循环输入,我的是降序排列。

一、冒泡排序

        时间复杂度为O(n^2),稳定的排序算法。

本质是相邻两个数字进行比较,外层for循环用于控制比较多少次,内层for循环用于逐次比较出每一个最小值。

for(i = 0; i < 5-1; i++)//五个数比较四次(len-1)
	{
		for (j = 0;j < 5-1-i; j++)//len-1-i
		{
			if (a[j] > a[j+1])
			{
				tmp = a[j];
				a[j] = a[j+1];
				a[j+1] = tmp;
			}
		}
	}

     二.选择排序 

        时间复杂度为O(n^2),不稳定的排序算法。

选择排序是将一个元素与数组中的所有元素,进行对比,每次比较找出一个最值,j是控制排了多少次,然后将i控制的值a[i]与j控制的值a[j]进行比较,(内层)每次都比较到了最后一个。

int min_num = 0;
	for (i = 0; i < 5-1; i++)//五个数比较四次(len-1)
	{
		min_num = i;
		for (j = i+1; j < 5; j++)//一直要找到最后一位
		{
			if (a[j] < a[min_num])
			{
				min_num = j;
			}
			if (min_num != i)
			{
				tmp = a[min_num];
				a[min_num] = a[i];
				a[i] = tmp;
			}//每次选择出来一个最小值
		}
	}

三、插入排序

        时间复杂度为O(n^2),稳定的排序算法。

所谓插入,就是在一个有序的序列中插入一个记录,确保插入后的序列仍然有序。如果原序列有序,那么插入排序的算法的效率是最高的。

此代码,i表示插入多少趟,j表示要插入的位置。

//插入
	for (i = 1; i < 5; i++)
	{
		tmp = a[i];//每次先保存a[i]的初值

		//j-1>=0==>j>0
		for (j = i; j>0 && tmp<a[j-1]; j--)//满足条件才进入此次循环
		{
			a[j] = a[j-1];//数据往后走,标号j往前走
		}
		a[j] = tmp;//这里的j可以到0
	}

四、哈希排序

时间复杂度为O(logn)~ O(n^2),不稳定的排序算法。

哈希排序。本质就是将一个待排序列分成若干个子序列,然后再利用插入排序的算法,对其进行排序。

此处我封装了一个API,参数a代表传入的数组名,和传入的长度。

每次找一个中间值inc进行分割,将分割前后的序列作为新的子序列,再进行插入排序。

void ShellSort(int *a, int len)
{
	int inc = 0;
	int i = 0;
	int j = 0;

	for(inc = len/2; inc > 0; inc/=2)
	{
		for(j = inc; j < len; j+=inc)
		{
			int tmp = a[j];
			for(i = j; a[i-inc] < tmp && i >= inc; i-=inc)
			{
				a[i] = a[i-inc];
			}
			a[i] = tmp;
		}
	}
}

五、快速排序

时间复杂度为O(logn),不稳定的排序算法。

每次选择一个基准值,经过一次快排之后,基准值的位置就是他自己在该序列中该有的位置,基准值左边全是比基准值小的序列,右边就是比基准值大的序列,第二次快排就是将左边或者右边的子序列再快排。然后递归去快排,直至每次快排都结束(传入的数组元素的头和尾相等)。

a:数组名         begin:数组第一个元素        end:数组的最后一个元素。

int QuilkSort(int *a, int begin, int end)
{
	if (begin >= end)
	{
		return 0;
	}
	int i = begin;
	int j = end;
	int key = a[i];

	while(i < j)//相等推出循环,一轮循环结束
	{
		while(i < j && a[j] >= key)
		{
			j--;
		}
		a[i] = a[j];//不合适就把后面不合适的值给前面
		while(i < j && a[i] <= key)
		{
			i++;
		}
		a[j] = a[i];//不合适接把前面不合适的给后面
	}
	a[i] = key;//键值归位

	QuilkSort(a, begin, i-1);//前半序
	QuilkSort(a, i+1, end);//后半序

}

相比与其他算法,快排是效率最高的,同时我也认为是逻辑较为为复杂的,于此同时,系统库函数给我们提供了一个快速排序的函数接口,

void qsort(void* base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*)); 

功能: 使用快速排序例程进行排序

参数:        1 待排序数组,排序之后的结果仍放在这个数组中
      2 数组中待排序元素数量
        3 一个元素的占用空间大小
             4 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)

第四个参数是一个函数指针,就是用户自己定义如何去排序。

//升序
int compare(const void*arg1, const void*arg2)
{
	const int *p1 = (const int *)arg1;
	const int *p2 = (const int *)arg2;

	return *p1-*p2;
}
//降序
int compare(const void*arg1, const void*arg2)
{
	const int *p1 = (const int *)arg1;
	const int *p2 = (const int *)arg2;

	return *p2-*p1;
}

//调用
qsort(a,len,sizeof(a[0],compare));

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值