排序算法

冒泡排序

先来个最简单的,一般都是最先接触的算法:冒泡排序

冒泡排序的思路也很简单,用升序排序来看,就是依次比较相邻的数字,如果前一个数字大于后面的那个,就交换两数(即把大数后移),假设数组长度为size,
第一轮比较完毕时,就把最大数移动到了 下标size-1 处

第二轮就在下标0到size-2中找到第二大的数字,并移动到下标size-2处,

循环往复,循环size-1 或 size轮即可完成排序

代码也很简单:

void BubbleSort(vector<int>& nums)
{
	int size = nums.size();
	//第一个for决定循环层数
	for (int i = size-1;i>0;--i)
	{//第二个for决定每一层里的循环次数
		for (int j = 0;j<i;++j)
		{
			if (nums[j] > nums[j + 1]) swap(nums[j], nums[j+1]);
		}
	}
}

快速排序

接下来介绍一下冒泡排序的升级版:快速排序
为什么说快速排序时冒泡排序的升级版,因为快速排序也是通过数组元素之间的比较交换来达成排序的

快速排序就是在一定的区间内找一个数字key,然后把整个区间分类,以升序为例,比key小的就放到左边,比key大的就放到key的右边,最后key就会被放到正确的位置上,然后获取key位置的下标,这此时整个区间就被key分成了两个部分
begin 到 key-1key+1 到 end
然后对这两个区间继续进行上面的步骤,直到把整个数组的所有数字都放到正确的位置上

于是我们直到,分割归位的程序时最重要的,
我们叫它partition (分割)

代码:

int partition(vector<int>&nums,int L, int R)
{
	int key = nums[L];//我们每次都取区间的第一个数作为key进行归位
	while(L < R)
	{//这里得注意,如果我们用nums[L]做基准,下面的while就得先对R进行判断,反之亦然,不然就会出错
		while(L < R && nums[R] >= key) --R;//满足大于key的条件就不用管了,找到不满足的再说
		swap(nums[L], nums[R]);//找到不满足的,进行交换
		while(L < R && nums[L] <= key) ++L;
		swap(nums[L], nums[R]);
	}
	return L;//执行完上面的程序之后,L == R不管返回那个都行,都是key的最终下标
}

这里我们每次都是用的nums[L]的值用作key,其实有更高效率的做法,那就是随机值

用rand在区间内随机一个下标keyidx,交换nums[L] 与 nums[keyidx],当然与nums[R]交换也是一样的,记得改while语句的顺序就好了

随机选择key值代码:

int keyidx = (rand()%(R-L+1))+L;//保证在L到R之间随机
swap(nums[L], nums[keyidx]);
key = nums[L];

当然,也可以提前在主函数里设置好时间随机种子

srand(time(NULL));

最重要的分割归位程序完成了其他的就简单了

分割程序语句决定好一个位置,并且把数组分成两部分了,那我们就继续对着两部分递归的进行分割归位,然后一路递归下去…直到数组中所有区间的上半部分被排序完,然后对区间的下班部分进行排序…(整个顺序可以随意改变,先上还是先下无所谓的)
代码:

void QSort(vector<int>&nums,int L, int R)
{
	if(L >= R)return;
	else
	{
		int idx = partition(nums, L, R);//切割排序获得第一个主元的下标
		QSort(nums, L, idx-1);//对下子区间进行分割归位
		QSort(nums, idx+1, R);//同理
	}
}

到这一步,快速排序已经完成了,我们只需要再封装一下就可以了
代码:

class Solution {
    int pratition(vector<int>& nums,int L, int R)
    {
        int keyidx = (rand()%(R-L+1))+L;
        swap(nums[keyidx],nums[L]);
        int key = nums[L];
        while(L < R)
        {
            while(L < R && nums[R] >= key) --R;
            swap(nums[L], nums[R]);  
            while(L < R && nums[L] <= key) ++L;
            swap(nums[L], nums[R]);          
        }
        return L;
    }
    void QSort(vector<int>& nums,int L, int R)
    {
    	if(L >= R) return;
        else
        {
            int idx = pratition(nums, L, R);
            QSort(nums, L, idx-1);
            QSort(nums, idx+1, R);
        }
    }
public:
    vector<int> QuickSort(vector<int>& nums) {
    	srand(time(NULL));
        int L = 0, R = nums.size()-1;
        QSort(nums,L,R);
        return nums;
    }
};

其实快速排序也意外的简单,写出partition程序就差不多了


归并排序

归并排序的思路如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
虽然思路是这样,但是意外程序执行的顺序和递归的性质,代码再执行的时候总是先排序某一边(看代码怎么写,可左可右)

在这里插入图片描述
代码:
主要程序:

void MSort(vector<int>&nums,int L, int R)
{
	if(L >= R)return ;
	else
	{
		int mid = L+((R-L)>>1);
		MSort(nums,L,mid);//先左
		MSort(nums,mid+1,R);//后右
		Merge(nums,L,mid,R);//合并
	}
}

合并的程序:

void Merge(vector<int>& nums,int L, int mid, int R)
{
	vector<int>temp(R-L+1);//临时数组
	int i = L, j = mid+1, idx = 0;
	while(i <= mid || j <= R)//合并而已,怎么写都行,下面会有另一种方法
	{
		int num1 = i <= mid?nums[i]:INT_MAX;
		int num2 = j <= R?nums[j]:INT_MAX;
		if(num1 <= num2)
		{
			temp[idx++] = num1;
			++i;
		}
		else
		{
			temp[idx++] = num2;
			++j;
		}
	}
	//合并完了就覆盖回原数组
	for(int i = 0;i<R-L+1;++i)  nums[L+i] = temp[i];
}

合并的另一种写法,用哪个都没差,不过这个更加简洁,也没有其他临时变量

while(i <= mid && j <= R)
{
	temp[idx++] = nums[i] <= nums[j]?nums[i++] : nums[j++];
}
while(i <= mid) temp[idx++] = nums[i++];
while(j <= R)	temp[idx++] = nums[j++];

封装:

class Solution {
	void Merge(vector<int>&nums, int L, int mid, int R)
	{
		vector<int>temp(R-L+1);
		int i = L, j = mid+1, idx = 0;
		while(i<=mid && j<=R) temp[idx++] = nums[i]<= nums[j]?nums[i++]:nums[j++];
		while(i<=mid) temp[idx++] = nums[i++];
		while(j<=R) temp[idx++] = nums[j++];
		for(int i = 0;i<R-L+1;++i)	nums[L+i] = temp[i];
	}
	
	void MSort(vector<int>&nums, int L, int R)
	{
		if(L >= R) return;
		else
		{
			int mid = L+((R-L)>>1);
			MSort(nums,L,mid);
			MSort(nums,mid+1,R);
			Merge(nums,L,mid,R);
		}
	}
public:	
	void MergeSort(vector<int>&nums)
	{
		int L = 0, R = nums.size()-1;
		MSort(nums,L,R);
	}
};


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timathy33

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值