排序算法集合(冒泡,插入,选择,快排

以从小到大排序举例,默认数组下标从 0开始
先从最简单的冒泡开始好了,就像他的名字,最大的数从原始位置一直冒冒冒冒到最后一位,对每一对相邻的元素进行比较,如果a[j]>a[j+1]就交换位置,比如 5 4 1 3 2 经过第一轮冒泡会变成 4 1 3 2 5。
因为一共有n个数,所以第一层循环要进行n趟排序;而在第一趟时的元素要与n-1个元素比较,而在第二趟时,第二趟的元素只需要与n-2个元素比较,其余依次类推。而下标从0开始,所以第二层循环要比较n-i-1次,代码如下:

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

接下来是插入排序,插入排序思想是将一个数插入到一组已经排好的数组中。
虽然给到的数据是混乱的,但我们可以把第一个元素就当一个有序的数组,而我们要将除第一个数外的所有数插入到这个有序数组中,所以第一层循环下标从1开始。在第二层循环中,每个元素只要与位于有序数组中的元素比较即可,所以下标从上一层下标开始,依次与排好序的数组中的元素比较,代码如下:

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

再接下来是选择排序,选择排序要选出所有待排数组中的最小值放在待排数组首位,所以我们可以每次都讲数组首位元素视为最小,然后依次比较,如果有比他更小的就先储存下标,比较完所有待排元素后在交换即可,代码如下:

void Selectsort(int a[],int n)
{
	for(int i=0;i<n-1;i++)
	{
		int min=i;
		for(int j=i+1;j<n;j++)
		{
			if(a[j]<a[min])
				min=j;
		}
		swap(a[i],a[min]);
	}
}

最后是快速排序,首先选待排数组第一个元素a[0]作为关键元素,将剩下的数分为小于a[0]和大于a[0]两部分,分别位于a[0]的左右两边。然后对这里两部分数组在执行依次上述操作,直到排好序,代码如下:

int partition(int a[],int l,int r)
{
	int key=a[l];
	int j=l;
	for(int i=l+1;i<=r;i++)
	{
		if(a[i]<key)
		{
			swap(a[j+1],a[i]);
			j++;
		}
	}
	swap(a[j],a[l]);
	return j;
}
void Quicksort(int a[],int l,int r)
{
	 if(l>=r)
	 return;
	 int p= partition(a,l,r);
	 Quicksort(a,l,p-1);
	 Quicksort(a,p+1,r);
}

这种用到递归的写法就相当于是对冒泡的一种改进,其实也有点二分查找的感觉,前两天在WB看到oppo的暑期实习面试题中就有一个问题是:
“快速排序的原理是什么?快速排序要用到递归来实现吗?数据特别大的时候,快排用递归会出现什么问题?怎么解决。”
(快速排序又称为分划交换排序,主要采取分治的主要思想)
然后我就想起要写这篇排序总结,但是对于这个问题我只能回答前半部分(果然还是垃圾啊 )于是我就去看了大佬们的非递归解法。大致就是当数据过大时,用递归就会爆栈(这个我也知道,但我不会优化 )然后非递归写法用到栈,然后我的数据结构学的一塌糊涂,搬一下大佬代码(原文链接

int pot(vector &a,int l,int r)
{
	int x = a[l];
	while(l<r)
	{
		while(l<r&&a[r]>=x)
			r--;
		a[l]=a[r];
		while(l<r&&a[l]<x)
			l++;
	}
	a[l]=x;
	return l;
}
void quicksort(vector a,int l ,int r)
{
	stack s;
	int k;
	s.push(l);
	s.push®;
	if(l<r)
	{
		while(!s.empty())
		{
			int j = s.top();
			s.pop();
			int i = s.top();
			s.pop();
			k=pot(a,i,j);
			if(i<k-1)
			{
				s.push(i);
				s.push(k-1);
			}
			if(k+1<j)
			{
				s.push(k+1);
				s.push(j);
			}
		}
	}
}

虽然我还是个小垃圾,但是我还是想吐槽一下原文作者的代码风格,每行都是顶格写,这样看起来真的好费力啊。
要是有解释不正确的地方还请各位大佬指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值