《插入排序》链接: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