直接插入排序

直接插入排序,插入排序(insert sort)的基本方法是:每步将一个待排序的元素,按其排序码大小,插入到前面已经排好序的一组元素的适当位置上去,直到元素全部插入为止。

算法描述:
直接插入排序(insert sort)的基本思想是:当插入第 i (i≥1)个元素时,前面的v[0],v[1]…VIi-1]已经排好序:这时,用V[i]的排序码与V[i-1],V[i一2],…的排序码顺序进行比较,找到插入位置即将V[i]插人,原来位置上的元素向后顺移。假设其中v[0],…v[i-1]已经是一组有序的元素,V[i],V[i+1],…,V[n-1]是待插入的元素,排序过程从i=1起,每一趟执行完后,i增加1,把第i个元素插入到前面有序的元素序列中去,使插入后元素序列V[0],V[1],…V[i]仍保持有序。

算法过程:

原始序列:3、44、38、5、47、15、36、 26、27、2、46、4、19、50、48

放上插入排序的动态图让大家更容易理解这个过程:

在这里插入图片描述结果:{2、3、4、5、19、26、27、36、38、44、46、47、48、50}

插入排序的C++,Java,Python实现

本篇文章会给大家介绍直接插入排序的三种语言的实现,在后面的文章中我会更新其他的插入排序,在这里先给大家分享简单一点的插入排序,循序渐进

插入排序C++实现代码:

#include <iostream>
using namespace std;
#include <vector>
#include <time.h>
vector<int> get_random(int n, int N);
const int MAX_NUM=10000;
int data[100];//定义一个产生数组储存100个随机数
void InsertSort(int n);//直接插入排序
void output(int n);
int main() 
{
	srand((unsigned int)time(0));
	vector<int> randsample=get_random(100,MAX_NUM);//产生100个0-MAZX_NUM的随机数,每次产生的随机数不一样
	int size=randsample.size();
	//输出最开始时未排序时的顺序:
	cout<<"随机数的顺序:"<<endl;
	for(int i=0;i<randsample.size();i++)
	{
		cout<<randsample[i]<<" ";
	}
	cout<<endl;
	clock_t start,finish;//定义一个测量一段程序运行时间的前后值
	double totaltime;//总的运行时间
	
	//测试插入排序
	cout<<"执行插入排序后:"<<endl;
	for(int i=0;i<randsample.size();i++)
	{
		data[i]=randsample[i];
	}
	start=clock();
	InsertSort(size);
	finish=clock();
	output(size);
	totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
	cout<<"运行时间:"<<totaltime<<endl;
}
//产生随机数的函数
vector<int> get_random(int n, int N)
{
	vector<int> vec(N);//N代表初始状态分配的空间大小
	vector<int> out_vec;
	for(int i=0;i<N;++i)
	{
		vec[i]=i;
	}
	for (int i=0;i<n;++i)
	{
		int rand_value=rand()%N;
		out_vec.push_back(vec[rand_value]);
		vec[rand_value]=vec[N-1];//将数组vec的元素
		N--;
	}
	return out_vec;
}
void InsertSort(int n)
{
	int tmp;
	int i,j;
	int count=0;
	int count1=0;
	for(i=1;i<n;i++){
		if(data[i]<data[i-1]){
			count++;
			tmp=data[i];
			j=i-1;
			while(j>=0&&tmp<data[j]){
				count++;
				data[j+1]=data[j];
				count1++;
				j--;
			}
			data[j+1]=tmp;
		}
	}
	cout<<"比较次数: "<<count<<"  移动次数:  "<<count1<<endl;
}
void output(int n)
{
	for(int i=0;i<n;i++)
	{
		cout<<data[i]<<" ";
	}
	cout<<endl;
}

测试结果展示:
在这里插入图片描述

插入排序Java代码实现

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class insertSort
{
  public static void main(String[] args)
  {
    Object []arr = getRandomNumList(100,0,10000).toArray();
    int[] ins = new int [100] ;
    System.out.println("排序前:");
    for(int i = 0; i < arr.length; i++) {
      String s=arr[i].toString();
      ins[i]= Integer.parseInt( s );
      System.out.println(ins[i]);
      }
    System.out.println("排序后:");
    int[] ins2 = insertsort(ins);
    for(int i = 0; i < arr.length; i++) {
      System.out.println(ins2[i]);
      }
  }
  
  public static int[] insertsort(int[] data){
	  int tmp;
	  int n = data.length-1;
		int i,j;
		for(i=1;i<=n;i++){
			if(data[i]<data[i-1]){
				tmp=data[i];
				j=i-1;
				while(j>=0&&tmp<data[j]){
					data[j+1]=data[j];
					j--;
				}
				data[j+1]=tmp;
			}
		}
    return data;
  }
   //定义生成随机数并且装入集合容器的方法
    //方法的形参列表分别为:生成随机数的个数、生成随机数的值的范围最小值为start(包含start)、值得范围最大值为end(不包含end)  可取值范围可表示为[start,end)
    public static List getRandomNumList(int nums,int start,int end){
        //1.创建集合容器对象
        List list = new ArrayList();

        //2.创建Random对象
        Random r = new Random();
        //循环将得到的随机数进行判断,如果随机数不存在于集合中,则将随机数放入集合中,如果存在,则将随机数丢弃不做操作,进行下一次循环,直到集合长度等于nums
        while(list.size() != nums){
            int num = r.nextInt(end-start) + start;
            if(!list.contains(num)){
                list.add(num);
            }
        }
        return list;
    }
}

插入排序Python代码实现

import random
def InsertSort(nums):
    for i in range(len(nums) - 1):
        if(nums[i]<nums[i-1]):
            tmp = nums[i]
            j = i - 1
            while(j>=0 and tmp<nums[j]):
                nums[j+1] = nums[j]
                j=j-1
            nums[j+1]=tmp

    return nums

def main():

    arr =[]
    while(len(arr)<100):
        x=random.randint(0,10000)
        if x not in arr:
            arr.append(x)
    InsertSort(arr)
    print(arr)

if __name__ == "__main__":
    main()

算法分析:

若设待排序的元素个数为n,则该算法的主程序执行n-1趟。因为排序码比较次数和元素移动次数与元素排序码的初始排列有关,所以在最好情况下,即在排序前元素已经按排序码大小从小到大排好序了,每趟只需与前面的有序元素序列的最后一个元素的排序码比较1次,总的排序码比较次数为n-1,元素移动次数为0。而在最差情况下,即第 i 趟时第 i 个元素必须与前面个元素都做排序码比较,并且每做1次较就要做1次数据移动,则总的排序码比较次数KCN和元素移动次数RMN分别为:

KCN= ∑ i = 1 n − 1 i \sum_{i=1}^{n-1}{i} i=1n1i=n(n-1)/2 ≈ \approx n 2 n^2 n2/2.
RMN= ∑ i = 1 n − 1 ( i + 2 ) \sum_{i=1}^{n-1}{(i+2)} i=1n1(i+2)=(n+4)(n-1)/2 ≈ \approx n 2 n^2 n2/2

从以上讨论可知,直接插入排序的运行时间和待排序元素的原始排列顺序密切相关。若待排序元素序列中出现各种可能排列的概率相同,则可取上述最好情况和最差情况的平均情况。在平均情况下的排序码比较次数和元素移动次数约为 n 2 n^2 n2/4。因此,直接插入挂序
的时间复杂度为O( n 2 n^2 n2)。直接插入排序是一种稳定的排序方法。

继续加油!

以上就是本次给大家分享的直接插入排序,后面还会写其他的插入排序,如果有什么不足之处欢迎大家指出,留言,互相学习,共同进步。希望得到大家的支持,你的支持就是我前进的动力,接下来我会持续更新其他的排序算法,敬请期待!(写博客学到了很多东西,嘻嘻,欢迎大家来我的个人博客玩耍啊)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值