先按自己思路全部写完,不用太过于急躁,出现一个问题,解决一个问题。
碰到的问题,1 快速排序的优化问题。中间提到。后面还有稳定性考虑,这点考虑的不是太多。
开始那三个排序
快速:每一次partition讲一个元素放入它应该在的位置。然后需要考虑的就是如何对于给定的数组中每一个元素都遍历到的问题。
最自然的想法,循环,但是在partition的过程中元素师变动的,可能导致有的元素被挪动多次,有的元素不能放到应有的位置。这样就牵扯到一个问题,需要对一个变动的数组进行遍历。然后就想到分治。每一次将一个元素排完序,然后对它前后两个组合进行此种操作就可以,然后很自然的思路就到了前面所说的二重递归的思路上。将数组不断地分成小的数组,他们互不相交。然后按照先序对于每一组元素进行某一个元素的位置放置。
然后是选元素问题。其实如果按算法最开始的思路,选任何一个元素都OK,但是后面如果牵扯到我们要用的递归的时候你要对于每一个元素都遍历都,这样可以选择的元素只有前两个后两个,还有(m+n)/2的情况。因为选别的数组里面可能会没有。
#include <random>
#include <time.h>
#include <iostream>
using namespace std;
class SortSet
{
private:
static int content[];
int length;
public:
SortSet(int size) : length(size){};
public:
int partition(int m, int n);
void QuickSort(int m, int n);
public:
void showContent();
};
void SortSet::showContent()
{
for (int i = 1; i <= length; i++)
cout<<content[i] <<" ";
cout<<endl;
}
int SortSet::content[] = {0,3,7,5,2,8};
int SortSet::partition(int m, int n)
{
int i = m-1;
int temp;
for (int j = m; j < n; j++)
{
if (content[j] < content[n])
{
i++;
temp = content[j];
content[j] = content[i];
content[i] = temp;
}
}
temp = content[++i];
content[i] = content[n];
content[n] = temp;
return i;
}
void SortSet::QuickSort(int m, int n)
{
if (m >= n)
return;
else
{
int temp = partition(m,n);
QuickSort(m,temp-1);
QuickSort(temp+1,n);
}
}
void main()
{
SortSet ss(5);
ss.showContent();
ss.QuickSort(1,5);
ss.showContent();
}
缺点,不稳定,对于基本有序的数组排序的时候会做很多无用功,数组比较短的时候快速排序并不是最快的。
随机化改进:不是选取第一个值为基准,而是随机选取。
平衡化改进:取第一个,最后一个很中间点三个值中间值为基准进行排序。
设置阈值:当数组长度小于某一值得时候用其他较快排序。
归并排序,其实这个算法我一直不知道它的存在意义。和快速是一样的思路,但是多了两个数组的额外空间。时间复杂度和快速排序是一样的。如果说后面说到的堆排序有一个作用是求得优先队列,那这个算法一直没有看出来它对于快速排序有任何一点优势。
好吧,这句记下来没事看看。然后提醒提醒自己学习过程中应该具有的深挖精神。不能仅仅的自己想当然看表象。
堆排序 从某种程度上来说更适合于求优先队列。
线性的时间复杂度的三个算法
基数排序, 计数排序, 桶排序