您的位置:首页 > 理论基础 > 数据结构算法

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

2015-09-27 16:28 387 查看
快速排序原理:选出一个基数,把小于这个基数的,放在它的前面,大于这个基数的放在基数后面。

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

第一种,不带哨兵的算法,这个时候我们首先看一下,怎么去理解这个东西。首先我们回忆一下,排序算法的思想,就是选取一个基数,把小于基数的数,放在基数的前面,把大于这个数的放在基数的后面。其实大家也许已经看出来了,其实重点就在怎么放,怎么比较。

首先把代码贴出来
#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: