前面我们介绍过了插入排序和选择排序。
插入排序,链接戳这里:http://blog.csdn.net/chaseraod/article/details/75091908
选择排序,链接戳这里:http://blog.csdn.net/chaseraod/article/details/75092407
本文我们学习交换排序。
交换排序分为冒泡排序和快速排序。
1,冒泡排序
冒泡排序的基本思想相信大家都已经不陌生。依次比较相邻的两个数,将小数放在前面,大数放在后面。
代码:
void BubbleSort(int *a, size_t n)
{
assert(a);
int end = n;
while (end > 0)
{
bool exchange = false;
for (int i = 0; i < end; i++)
{
if (a[i - 1]>a[i])
{
swap(a[i - 1], a[i]);
exchange = true;//说明已经有序
}
}
if (exchange == false)
{
break;
}
--end;
}
}
测试:
int main()
{
int a[] = { 1, 5, 3, 2, 8, 0, 7, 9, 4, 6 };
int sz = sizeof(a) / sizeof(a[0]);
BubbleSort(a, sz);
for (int i = 0; i < sz; i++)
{
cout << a[i] << " ";
}
cout << endl;
system("pause\n");
return 0;
}
运行结果:
2,快速排序
快速排序是面试中最常考的,这里我们给出三种快速排序的方法。
(1)左右指针法:
基本思想:选出一个key值,begin去查找数组中比key大的值,end去查找数组中比key小的值,递归子问题。可以知道的是,当数组正好是逆序时,快排的效率最低,为了防止最坏的情况,我们采取三数取中法。
代码:
//三数取中法
int GetMidIndex(int* a, int left, int right)
{
int mid = left + (right - left) / 2;
// left mid right
if (a[left] < a[mid])
{
if (a[mid] < a[right])
return mid;
else if (a[left] > a[right])
return left;
else
return right;
}
else // left > mid right
{
if (a[mid] > a[right])
return mid;
else if (a[left] < a[right]) // right > mid
return left;
else
return right;
}
}
// 左右指针法
int PartSort1(int* a, int left, int right)
{
int mid = GetMidIndex(a, left, right);
swap(a[mid], a[right]);
int key = a[right];
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[begin] <= key)
{
++begin;
}
while (begin < end && a[end] >= key)
{
--end;
}
if (begin < end)
swap(a[begin], a[end]);
}
swap(a[begin], a[right]);
return begin;
}
(2)挖坑法
将a[right]赋值给key,右边就成了一个“坑”,再用left去找比key大的放到右边的坑,用right找比key小的放到左边的坑,当left和right相遇时,是key值的位置。
int PartSort2(int *a, int left, int right)
{
int key = a[right];
while (left < right)
{
while (left < right && a[left] <= key)
{
++left;
}
a[right] = a[left];
while (left < right && a[right] >= key)
{
--right;
}
a[left] = a[right];
}
a[left] = key;
return left;
}
(3)前后指针法
定义一个prev在cur之前,若cur
int PartSort3(int* a, int left, int right)
{
int prev = left - 1;
int cur = left;
int key = a[right];
while (cur < right)
{
if (a[cur] < key && ++prev != cur)
{
swap(a[prev], a[cur]);
}
++cur;
}
swap(a[++prev], a[right]);
return prev;
}
测试:
//递归解法
void QuickSort(int *a, int left, int right)
{
assert(a);
if (left > right)
return;
if (right - left < 10)
{
InsertSort(a + left, right - left + 1);//小区间优化,提高快排效率
}
if (left < right)
{
int div = PartSort2(a, left, right);
QuickSort(a, left, div - 1);
QuickSort(a, div + 1, right);
}
}
//非递归
#include <stack>
void QuickSortNonR(int* a, int left, int right)
{
assert(a);
stack<int> s;
if (left < right)
{
s.push(right);//栈 先进后出
s.push(left);
}
while (!s.empty())
{
int begin = s.top();
s.pop();
int end = s.top();
s.pop();
int div = PartSort1(a, begin, end);
if (begin < div - 1)
{
s.push(div - 1);
s.push(begin);
}
if (div + 1 < end)
{
s.push(end);
s.push(div + 1);
}
}
}
int main()
{
int a[] = { 1, 5, 3, 2, 8, 0, 7, 9, 4, 6 };
int sz = sizeof(a) / sizeof(a[0]);
QuickSort(a,0,sz-1);
for (int i = 0; i < sz; i++)
{
cout << a[i] << " ";
}
cout << endl;
system("pause\n");
return 0;
}
运行结果: