排序——交换排序 主要包括:《冒泡排序》《快排—四种快排方法》

插入排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89345756
选择排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89363420
交换排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89394853
归并排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893
非比较排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893

交换排序的思想:就是将再序列中标记的两个值,进行交换,我们将较大的值往后移动,将较小的值往前移动。

(1)冒泡排序

冒泡排序的思想:就是把第一个值与后面的值全部进行比较,并且交换,直到找到自己位置,然后重复这个过程。

下面是我们是实现的代码;

void BubbleSort(int* a, int n) //没有优化之前的
{
	    int i = 0;
	    int end = n ;
		while (end > 0)
		{
			for (i = 1; i <= end - 1; i++)
			{
				if (a[i - 1] > a[i])
				{
					Swap(&a[i - 1], &a[i]);

				}
		     }
			--end;
	    }
}

void BubbleSort2(int* a, int n) //冒泡排序,遍历有序是快速
{
	int i = 0;
	int end = n;
	while (end > 0)
	{
		int change = 0;
		for (i = 1; i <= end - 1; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				change = 1;
			}
		}
		if (change = 0)
		{
			break;
		}
		--end;
	}
}

冒泡排序是比较慢的,相比较希尔排序,和堆排序。但是他比选择排序排序要快,且和插入排序差不多。

(2)快速排序—《这里是重点》

(a.)快速排序——hoare排序,

hoare的思想是:在序列中选择一个数为基准,将该序列分成两个组,然后进行遍历,将比他大的值,往后移动,比他小的值往移动,然后重复此过程,知道所有的数都到了他该在的顺序上。
在这里插入图片描述

在这里插入图片描述
下面我看一下是的代码:

int PartSort(int* a, int begin, int end)
{
	int key = begin;//基准值
	while (begin < end)
	{
	while (begin < end && a[end] >= a[key])
		--end;

	while (begin < end && a[begin] <= a[key])
		++begin;
	Swap(&a[begin], &a[end]);
}
Swap(&a[key], &a[end]);

return end;
}

void QuickSort(int* a, int left, int right)
{

if (left >= right)
	return;
int div = PartSort(a, left, right);
QuickSort(a, left, div - 1);   //以基准值进行分开,前div-1,
QuickSort(a, div + 1 , right);  //后div+1
}

(b.)三数取中法

一定不会找最小的值最key,或者最大值做key;,但是还是要找中间的值,比小的大,比大的小。

比如 : begin < mid <end;

在这里插入图片描述

下面我们看一下实现的代码:

int GetMidIndex(int* a, int begin, int end) //主要是怕是有序的时候,这个快排就非常慢;加这个就快的很;
{
	int mid = 0;
	mid = begin + ((begin - end) >> 1);
	if (a[begin] < a[mid])
	{
		if (a[mid] < a[end])
		{
			return mid;
		}
		else if (a[begin] > a[end])
		{
			return begin;
		}
		else
			return end;
	}
	else   //mid < begin
	{
		if (a[mid] > a[end])
		{
			return mid;
		}
		else if (a[begin] < a[end])
		{
			return begin;
		}
		else
			return end;
	}

}
int PartSort2(int* a, int begin, int end)   三数取中法
{
	int key = 0;
	int mid = GetMidIndex(a, begin, end);
	Swap(&a[begin], &a[mid]);
	key = begin;
	while (begin < end)
	{
		//end找小;
		while (begin < end && a[end] >= a[key])
			--end;
	//end找大;
	while (begin < end && a[begin] <= a[key])
		++begin;

	Swap(&a[begin], &a[end]);
}
Swap(&a[key], &a[end]);
return end;
}

这个排序就是三数取中法,它是第一种快排的优化。但是他在有序的情况下面相比较堆排序,或者希尔排序慢一点,但是再无序的情况下面也是非常快的,

下面还有一种快排。
(3)挖坑法

挖坑法的思想;主要是先找一个基准的值(mid),然后把这个拿出来,在让前后指针左右走,先让右边的先走,然后让左边的走,右找小,左找大,就像下面我画的一幅图:

在这里插入图片描述
下面我们看一下实现的代码:

int PartSort3(int* a, int begin, int end)     //挖坑法
{
	int mid = a[begin];
	while (begin < end)
	{
		//end找小;
		while (begin < end && a[end] >= mid)
			--end;
		a[begin] = a[end];  //不像之前的交换,这里是直接把最后的给到坑里面。
		//end找大;
		while (begin < end && a[begin] <= mid)
			++begin;
		a[end] = a[begin];
	}
	a[begin] = mid;

	return begin;
 }

是不是感觉这个和第一种排序的代码差不多,确实是这个样子,但是这两种的思想是不一样的。

(4)左右指针法

左右指针法的思想:主要是,有两给指针: cur , prev。 cur = begin+1,prev = begin。先让cur先走,找比当前 bengin 小的值,然后让 prev 一起,前面都是小于他的值,自己和自己交换,不用管,然后继续往后面走,如果比他小就交换,两者就进行交换。直到 cur 走完,然后把prev和begin在一交换,这样就可找到,前面的值,比他大,后面的值比他小。

在这里插入图片描述

int PartSort4(int* a, int begin, int end)//左右指针法
{
	//int count = begin;
	int key = begin;
	int prev = begin;
	int cur = begin + 1;
	while (cur <= end)
	{

		if (a[cur] <= a[key] && prev++ != cur)   //prev不等于cur才进行交换
		{
			Swap(&a[prev], &a[cur]);

		}
		++cur;
	}
	Swap(&a[key], &a[prev]); 
	/*printf("\n");
	for (; count<end; ++count)
	{

		printf(" %d ", a[count]);


	}printf("\n");*/
	return key;
}

这几种快排的方法,使用的不同的原理,但是基本思想都是交换的思想。下面我们就看一下,快排和冒泡的区别;

冒泡排序;

1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:稳定

快排:

1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
2. 时间复杂度:O(N * logN)
3. 空间复杂度:O(logN)
4. 稳定性:不稳定

再给出快排接口优化版本实现代码:

void QuickSort(int* a, int left, int right)  //6.快排
{
	int div = 0;
	if (left >= right)
		return;
	//没有优化过版本;
	/*div = PartSort4(a,left,right);
	QuickSort(a,left, div-1);
	QuickSort(a,div+1,right);*/

	//优化过的版本;
	if (right - left > 10)
	{
		div = PartSort3(a, left, right);
		QuickSort(a, left, div - 1);
		QuickSort(a, div + 1, right);
	}
	else
	{
		InsertSort(a + left, right - left + 1);  //小于10个数,直接用插入排序就可以了。
	}

}

在前面的如果像进行测试,可以使用前面插入排序中的测试代码,可以进行测试。

插入排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89345756
选择排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89363420
交换排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89394853
归并排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893
非比较排序》链接:https://blog.csdn.net/dpfxaca6/article/details/89449893

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值