文章目录
本博文源于浙江大学《数据结构》,姥姥今天讲的插入排序是为后续的排序打下了深厚的基础,就是因为这个,我们方能在后续的排序中游刃有余,在为后续插入排序实现时,先记住这几个结论:
插入排序情况分析:
最好情况(N-1):顺序T=O(N)
最坏情况:逆序T=O(N^2)
空间复杂度O(1)
算法执行效果稳定
总的关键字比较次数KCN = n^2/2
记录移动次数RMN =n^2/2
平均的话,比较次数和移动次数都是n^2/4
算法分析:
- 稳定排序
- 算法简单,且容易实现。
- 也适合用于链式存储结构,只是在单链表上无需移动记录,只需要修改相应的指针。
- 更适合于初始记录基本有序的情况,当初始记录无序,n较大,次算法时间复杂度较高,不宜采用。
目前评价算法好坏主要有两点:
- 执行时间
- 辅助空间
时间复杂下界
插入排序的时间复杂度下界是N^2
逆序对
对于下标i<j,如果A[i]>A[j],则称(i,j)是一对逆序对.
测试
序列{38,8,64,51,32,21}中有多少个逆序对?
(38,8),(34,32)(34,21)(64,51)(64,32)(64,21)(51,32)(51,21)(32,21)
定理1 交换2个相邻元素正好消去1个逆序对
插入排序:T(N,I) = O (N+I)
N就是元素的个数,I就是逆序对的个数
定理2 任意N个不同元素组成的序列平均具有N(N-1)/4个逆序对
定理3 任何仅以交换相邻两元素来排序的算法,其平均时间复杂度下界为N^2
总结
如果在后续的排序中,消除逆序对就是不止一个,一次如果消除不止一个逆序对,那么排序的效率会越来越高!
测试用例
int arr[5] = {5,3,1,6,2};
用整型数组作为容器,5可以由里面的元素进行改变。这样防止手动输入浪费编程可视化效果时间。
插入排序源码(教科书)
void InsertSort(int r[]){
int i,j;
for(i =2;i<=4;++i){
if(r[i] < r[i-1]){
r[0] = r[i];
r[i] = r[i-1];
for(j = i-2;r[0]<r[j];--j){
r[j+1] = r[j];
}
r[j+1] = r[0];
}
}
}
源码附上(插入排序)
#include<stdio.h>
typedef int ElementType;
void Print_Array(ElementType A[],int N)
{
printf("\n");
for(int i=0;i<N;i++)
printf("%d ",A[i]);
}
void Insertion_Sort(ElementType A[], int N)
{
int i = 0;
for(int P=1;P<N;P++) {
int Tmp = A[P];
for(i = P;i>0 && A[i-1] > Tmp;i--)
A[i] = A[i-1];
A[i] = Tmp;
}
}
int main()
{
int arr[5] = {5,3,1,6,2};
Print_Array(arr,5);
Insertion_Sort(arr,5);
Print_Array(arr,5);
return 0;
}
折半插入排序源码
教科书源码
void BInsertSort(SqList &L){
for(int i =2;i<=L.length;i++){
L.r[0] = L.r[i]; //监视岗位
int low = 1; //置查找区间初值
int high = i-1; //在r[low,high]中折半查找插入的位置
while(low <= high){
int m = (low+high)/2; //折半
if(L.r[0].key < L.r[m].key)
high = m-1; //前一个子表
else low = m+1; //后一个子表
}
for(int j =i-1;j>=high+1;--j)
L.r[j+1] = L.r[j] //记录后移
L.r[high+1] = L.r[0] //插入到正确位置
}
}
//1、已知一维数组,转换为相应特殊矩阵并打印。输入:
//1)请输入特殊矩阵类型:a 对称矩阵,b 下三角矩阵,c 带状矩阵,d 稀疏矩阵
//2)请输入矩阵维度
//3)请输入一维数组值
//4)输出:打印相应矩阵
#include<iostream>
#include<cstdio>
using namespace std;
typedef int ElementType;
void Print_Array(ElementType A[],int N)
{
printf("\n");
for(int i=1;i<N;i++)
printf("%d ",A[i]);
}
void BInsertSort(int arr[],int n){
for(int i =2;i<=n;i++){
arr[0] = arr[i]; //监视岗位
int low = 1; //置查找区间初值
int high = i-1; //在r[low,high]中折半查找插入的位置
while(low <= high){
int m = (low+high)/2; //折半
if(arr[0] < arr[m])
high = m-1; //前一个子表
else low = m+1; //后一个子表
}
for(int j =i-1;j>=high+1;--j)
arr[j+1] = arr[j]; //记录后移
arr[high+1] = arr[0]; //插入到正确位置
}
}
int main(){
int n=5;
int arr[n] ={-1,-2,7,5,2};
Print_Array(arr,n);
BInsertSort(arr,n);
Print_Array(arr,n);
return 0;
}