(C语言浙大版)插入含折半插入排序并分析逆序实现


本博文源于浙江大学《数据结构》,姥姥今天讲的插入排序是为后续的排序打下了深厚的基础,就是因为这个,我们方能在后续的排序中游刃有余,在为后续插入排序实现时,先记住这几个结论:

插入排序情况分析:
	最好情况(N-1):顺序T=O(N)
	最坏情况:逆序T=O(N^2)
	空间复杂度O(1)
	算法执行效果稳定
	总的关键字比较次数KCN = n^2/2
	记录移动次数RMN =n^2/2
	平均的话,比较次数和移动次数都是n^2/4
	
	
算法分析:

 - 稳定排序
 - 算法简单,且容易实现。
 - 也适合用于链式存储结构,只是在单链表上无需移动记录,只需要修改相应的指针。
 - 更适合于初始记录基本有序的情况,当初始记录无序,n较大,次算法时间复杂度较高,不宜采用。

目前评价算法好坏主要有两点:

  1. 执行时间
  2. 辅助空间

时间复杂下界

插入排序的时间复杂度下界是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值