排序 算法

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
排序在生活中还是很常见的 如 考试成绩排名 网购时商品价格等的排名 足球队伍身价排名 等等

而我们今天要讨论的是关于排序的算法
首先 给你一组简单的乱序数字 让你对他进行排序 你会怎么样选择
可能很多同学都会想起冒泡排序 我也是 因为它最好写 嵌套两个循环就可以了
但你有没有想过 他的时间复杂度 空间复杂度
让我们来看看常见的排序算法 它们在时间空间上孰优孰劣
在这里插入图片描述
插入排序:
其主要思想把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。时间复杂度 O(n^2)空间复杂度 O(1)
而希尔排序就是直接插入的进阶版 先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。 时间复杂度 O(n^1.3)空间复杂度 O(1)

//直接插入排序
void insertsort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int temp = a[i + 1];
		while (end >= 0)
		{
			if (a[end] > temp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
				break;
		}
		a[end+1]=temp;
	}
}
//希尔排序
void shellsort(int* a, int n)
{
	int gap = n;
	while(gap>1)
	{
		gap /= 2;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int temp = a[i + gap];
			while (end >= 0)
			{
				if (a[end] > temp)
				{
					a[end + gap] = a[end];
					end-=gap;
				}
				else
					break;
			}
			a[end + gap] = temp;
		}
	}
}

选择排序:
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。时间复杂度 O(n^2)空间复杂度 O(1)

void selectsort(int* a, int n)
{
	int bigan=0,end=n-1;
	while (bigan<end)
	{
		int max = bigan, min = bigan;
		for (int i = bigan; i <= end; i++)
		{
			if (a[i] > a[max])
				max = i;
			if (a[i] < a[min])
				min = i;
		}
		swap(&a[bigan++],&a[min]);//swap就是一个交换函数
		swap(&a[end--], &a[max]);
	}
}

堆排序:
指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
时间复杂度 O(nlogn)空间复杂度 O(1)

void hpmovedown(heap* hp, int end, int parent)
{
	assert(hp);

	int child = parent * 2 + 1;
	while (child < end)
	{
		if (child + 1 < end && hp->a[child + 1] compare hp->a[child])
			child = child + 1;

		if (hp->a[child] compare hp->a[parent]) // > 大堆 < 小堆
			swap(&hp->a[child], &hp->a[parent]);

		parent = child;
		child = parent * 2 + 1;
	}
}

//> 大堆升序 < 小堆降序
void hpqsort(heap* hp)
{
	int n = hp->size - 1;
	while (n > 0)
	{
		swap(&(hp->a[0]), &(hp->a[n]));
		hpmovedown(hp, n, 0);
		n--;
	}
}

冒泡排序:
就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,每一次遍历都确定一个最大或者最小值 时间复杂度 O(n^2)空间复杂度 O(1)

void bubblesort(int* a, int n)
{
	for(int i=0;i<n-1;i++)
		for (int j = 0; j < n - i - 1; j++)
		{
			if (a[j] > a[j + 1])
				swap(&a[j],&a[j+1]);
		}
}

快速排序:
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。时间复杂度 O(nlogn)空间复杂度 O(logn)

//升序
void quicksort1(int* a, int bigan, int end)
{
	if (((end-bigan) + 1) <= 10)
	{
		insertsort(&(a[bigan]),end-bigan+1);
	}
	else
	{
		if (bigan >= end)
		return;

		int left = bigan, right = end;
		int mid = getmid(a,left,right);
		int key = left;
		swap(&(a[mid]),&(a[key]));
		while (left < right)
		{
			while (left < right && a[right] >= a[key])
				right--;

			while (left < right && a[left] <= a[key])
				left++;
	
			swap(&(a[left]), &(a[right]));
		}
		swap(&(a[left]), &(a[key]));
		key = left;

		quicksort1(a, bigan, key - 1);
		quicksort1(a, key + 1, end);
	}
}

归并排序:
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:
在这里插入图片描述
时间复杂度 O(nlogn)空间复杂度 O(n)

void _mergesort(int* a, int left, int right,int* tmp)
{
	if (left >= right)
		return;
	int mid = (right + left) / 2;

	_mergesort(a,left,mid,tmp);
	_mergesort(a, mid+1, right, tmp);

	int num = left;
	int bigan1 = left, end1 = mid, bigan2 = mid + 1, end2 = right;
	while (bigan1<=end1 && bigan2<=end2)
	{
		if (a[bigan1] < a[bigan2])
			tmp[num++] = a[bigan1++];
		else
			tmp[num++] = a[bigan2++];
	}
	while (bigan1 <= end1)
	{
		tmp[num++] = a[bigan1++];
	}
	while (bigan2 <= end2)
	{
		tmp[num++] = a[bigan2++];
	}

	memcpy(a+left,tmp+left,sizeof(int)*(right-left+1));
}

void mergesort(int* a, int n)
{
	int* tmp = (int *)malloc(sizeof(int)*n);
	if (tmp == NULL)
	{
		perror("mergesort malloc:");
		exit(-1);
	}

	_mergesort(a,0,n-1,tmp);
}

以上算法实现方法都有很多 不一一列举 主要理解思想;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值