数据结构------快排及另类快排思想解决问题

快速排序原理:选出一个基数,把小于这个基数的,放在它的前面,大于这个基数的放在基数后面。

首先:我觉得大家肯定都很疑惑,算法这个东西,思想掌握了,但是代码的实现,又有很多种,就比如拿今天我们的主人公,快速排序来说吧,这个算法有两种形式,一种是不加哨兵的算法,一种是加上哨兵的算法,我曾经一度以为这两个形式是两种算法,让我走了好多弯路。我想我这样说肯定是的不到大家的理解的,那么我们接下来就进入今天的主要内容。

 

  1. 第一种,不带哨兵的算法,这个时候我们首先看一下,怎么去理解这个东西。首先我们回忆一下,排序算法的思想,就是选取一个基数,把小于基数的数,放在基数的前面,把大于这个数的放在基数的后面。其实大家也许已经看出来了,其实重点就在怎么放,怎么比较。
  • 首先把代码贴出来
  • #include <iostream>
    using namespace std;
    
    void  Swap(int &a, int &b)
    {
    	int tmp;
    	tmp = a;
    	a = b;
    	b = tmp;
    }
    
    void QuickSort(int *arr,int left,int right)
    {
    	if (arr == NULL)
    		return;
    	int low = left;
    	int high = right;
    
    	//不设置哨兵的写法
    	while (low < high)
    	{
    		while (low < high && arr[low] <= arr[high])   high--;
    		
    		Swap(arr[low], arr[high]);
    		
    		while (low < high && arr[low] <= arr[high])   low++;
    		
    		Swap(arr[low], arr[high]);
    	}
    	//在这里把要排序的数字,分成两部分,然后选取前半部分,进行递归算法
    	if (low - 1 >= left)
    		QuickSort(arr, left, low-1);
    	//当第一部分的前半部分进行递归完了之后,在计算他左边的
    	if (high + 1 <= right)
    		QuickSort(arr, high+1, right);	
    }
  • 首先我们来分析一下这段代码。核心部分是while里面的那部分,首先当low小于high的时候,我们的代码是一直进行第一次循环的,因为要遍历完所有的数。
  • 1.这个时候,我们刚开始进行比较的时候,我们一定要让high先动,为什么呢,因为这个时候我们让默认的基数为low指向的地方。然后如果low小于high则一直让high一直向前移动,这个时候如果high小于了low,则对high与low进行交换。
  • 2.交换完了,等于说high的位置变成了,基数的位置。然后我们对此时的low与high进行比较,如果low小于high则一直,low++,如果low大于了high则停下来,交换。
  • 3.这个时候,while里面的第二个while也执行完了,这个时候,毫无疑问,需要进行需要判断,是否结束while循环,如果low没有与high重合,则步骤如上。
  • 4.当while循环结束的时候,也就是,这个时候(假设是第一次循环的结束),我们把数组分为两部分,left到low,high到right,这个时候我们进行左半部分的排序,然后进行递归,左半部分,会继续分为更小的两部分,直到递归到两个数,也就是重合的时候,这个时候,就会return。我们的递归调用函数,会一直跳转回,第一次分割的地方,然后进行右半部分的递归调用。
  • 也许大家看完我的文字描述,还有一些疑惑,下来我来上一幅图
                                                                                        快速排序函数的递归调用
2.第二种,带哨兵的快速排序。
首先我们在这里说这两个的区别:
  • 不带哨兵的函数:我们在交换数组里面的值时候,我们总是,当基数为low的时候,把low与high直接一换,则此时high为基数,然后在用low与high进行比较,满足交换的条件了,用low与high交换,这个时候基数又变成high,当俩重合的时候,基数刚好就在他们中间。
  • 带哨兵的函数:开始进行比较的时候,对基数进行记录为tmp,然后用low与high进行比较,当low与high进行重合的时候,把low与high位置的数放在left的位置,然后把tmp放在low的位置。
#include <iostream>
using namespace std;

void  Swap(int &a, int &b)
{
	int tmp = 0;
	tmp = a;
	a = b;
	b = tmp;
}
void QuickSort(int *arr, int left, int right)
{
	if (arr == NULL)
		return;
	int low = left;
	int high = right;

	int tmp = arr[left];
	while (low < high)
	{
		while (low < high && arr[high] >= tmp) high--;
	
		while (low < high && arr[low] <= tmp)low++;
		
		if (high != low)
		{
			Swap(arr[high], arr[low]);
		}
	}
	//数据归位
	arr[left] = arr[low];
	arr[low] = tmp;


	if (low - 1 >= left)
		QuickSort(arr, left, low - 1);

	if (high + 1 <= right)
		QuickSort(arr, high + 1, right);
}

这个代码贴出来,大家可以在电脑上自己运行一把,思想什么的都一样,我就不赘述了。

    
 
下面我们来看一道,有关快排思想的运用的题:给你一个数组,按序列排好如:1,4,7,9,11,12,14,15,这个时候,输入一个数字,例如15,输出数组里两个数,刚好等于15,如1+14 = 15;
#include <iostream>
using namespace std;

void func(int *a,int szie_num,int aim_num)
{
	int *p = a;
	int *q = p + szie_num;
	while (p != q)
	{
		if ((*p + *q) > aim_num)
		{
			q--;
		}
		else if ((*q + *p) < aim_num)
		{
			p++;
		}
		else
			break;
	}
	printf("%d + %d = %d", *p, *q, aim_num);
}

 
 
 
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值