0.排序算法总论
算法设计要点
- 等号有没有的问题
有没有等号,关键看项目需求,关注算法的本质含义
例如:对于“折半查找方式” 允许low=high;
对于“保证元素数量>=2”则不允许low=high
1.排序算法的核心思想
核心思想
- 定位、遍历、递归【注意递归成立的前提条件】
- 比较
- 移动
- 特殊情况
核心关注点
- 关于“=”
- 关于“+1,0,-1”
2.插入排序
2.1.直接插入排序
/*基于线性表,从小到大排序*/
//直接插入排序【第5次】
bool InsertSort(int a[],const int &n)
{
if(n <= 0)
return false;
for(int i = 1;i < n;i++)
{
if(a[i] < a[i-1])
{
int j = i-1;
int tmp = a[i];
while(j >= 0 && tmp < a[j])//【思维纠正】tmp小,就往前走,直到不小为止
{
a[j+1] = a[j];
j--;
}
a[j+1] = tmp;
}
}
return true;
}
2.2.折半插入排序
//折半插入排序
bool BinInsertSort(int a[],const int &n)
{
if(n <= 0)
return false;
for(int i = 1;i < n;i++)
{
if(a[i] < a[i-1])
{
int low = 0,high = i-1,mid;
int tmp = a[i];
while(low <= high)
{
mid = (low+high)/2;
if(tmp < a[mid])
high = mid-1;
else
low = mid+1;
}
for(int j = i-1;j > high;j--)
a[j+1] = a[j];
a[high+1] = tmp;
}
}
return true;
}
2.3.希尔排序
当d=1的时候,“希尔排序”退化为“标准直接插入排序”
原始数据
int a[] = {9,5,4,38,1,2,20,21};
int len = sizeof(a)/sizeof(a[0]);
备注:输出的是每一趟的结果
i++是正确写法,是希尔排序,但是写的时候产生了一个错误,写成了i += d,这样是什么结果呢?
这样的话,基本上跟“直接插入排序”没有什么区别了,因为d=1的时候交换次数最多
【希尔排序的本质】:尽可能地减少d = 1时候的交换次数,d越大,交换地越多,这样才能减少总体交换时间(这里谈及的是n!不是个例!)
拓展:用内部折半插入进行排序希尔排序(内部折半插入)
3.交换排序
3.1.冒泡排序
3.1.1.关键字:循环,锁定
3.2.快速排序
3.2.1.关键字
- 一次划分
- 递归(分治思想,自上而下)
3.2.2.一句话
符合移动,不符不动,相等均符合
3.2.3.算法描述&算法本质
3.2.4.算法实现:算法一
【注意】本算法的易错点:“tmp >= a[i] <= a[j]”,一定要加上“=”,否则会进入无限比较(例如 4,6,7,1,4 会在4…4无限比较4,但就是不能移动)
//快速排序
int partition(int a[],int low,int high)//一次划分
{
if(low < 0 || high < 0)
return false;
int i = low,j = high;
int tmp = a[i];
while(i < j)
{
while(i < j && tmp <= a[j])//注意等号
j--;
a[i] = a[j];
while(i < j && tmp >= a[i])//注意等号
i++;
a[j] = a[i];
}
a[i] = tmp;
return i;
}
bool QuickSort(int a[],int low,int high)//递归调用划分
{
if(low < 0 || high < 0)
return false;
if(low < high)
{
int i = partition(a,low,high);
QuickSort(a,low,i-1);
QuickSort(a,i+1,high);
}
return true;
}
3.2.5.算法评价
3.2.5.1.时间复杂度分析
3.2.5.2.空间复杂度分析
3.2.5.3.稳定性分析
3.2.5.4.应用分析
3.2.6.算法实战
对于大量数据,算法需要进行优化,否则会因为“递归深度过高”导致“堆栈溢出”,算法失效!
4.选择排序
4.1.简单选择排序
4.1.1.关键字:循环,锁定
4.2.堆排序
5.归并排序
关键字:
- 一次归并
- 递归(分治思想,自上而下)
核心算法
- 递归调用,不断拆分,直到每个有序表都只有一个元素
- 对每两个有序表合并
- 递归返回,重复2过程
- 得出结果
核心函数
- Merge 一次归并函数
- MergeSort 归并函数