【数据结构】排序算法---直接插入排序

文章目录

  • [1. 定义](#1. 定义)
  • [2. 算法步骤](#2. 算法步骤)
  • [3. 动图演示](#3. 动图演示)
  • [4. 性质](#4. 性质)
  • [5. 算法分析](#5. 算法分析)
  • [6. 代码实现](#6. 代码实现)
  • [7. 折半插入排序](#7. 折半插入排序)
  • 结语

1. 定义

直接插入排序是一种简单直观的排序算法。它的工作原理为将待排列元素划分为「已排序」和「未排序」两部分,每次从「未排序的」元素中选择一个插入到「已排序的」元素中的正确位置。

直接插入排序的代码实现虽然没有冒泡排序和选择排序那么简单粗暴,但它的原理应该是最容易理解的了,因为只要打过扑克牌的人都应该能够秒懂。

直接插入排序和冒泡排序一样,也有一种优化算法,叫做折半插入

2. 算法步骤

一般来说,直接插入排序都采用in-place在数组上实现。具体算法描述如下:

  1. 从第一个元素开始,该元素可以认为已经被排序;

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;

  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

  5. 将新元素插入到该位置后;

  6. 重复步骤2~5。

3. 动图演示

4. 性质

稳定性

直接插入排序是一种稳定的排序算法。

空间复杂度

直接插入排序的空间复杂度为 O ( 1 ) O(1) O(1)。

时间复杂度

  • 元素集合越接近有序,直接插入排序算法的时间效率越高。

  • 直接插入排序的最优时间复杂度为 O ( n ) O(n) O(n),在数列几乎有序时效率很高。

  • 直接插入排序的最坏时间复杂度和平均时间复杂度都为 O ( n 2 ) O(n^2) O(n2)。

5. 算法分析

直接插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

6. 代码实现

C语言

c 复制代码
void insertion_sort(int arr[], int len){
        int i,j,key;
        for (i=1;i<len;i++){
                key = arr[i];
                j=i-1;
                while((j>=0) && (arr[j]>key)) {
                        arr[j+1] = arr[j];
                        j--;
                }
                arr[j+1] = key;
        }
}

Python

python 复制代码
def insertionSort(arr):
    for i in range(len(arr)):
        preIndex = i-1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex+1] = arr[preIndex]
            preIndex-=1
        arr[preIndex+1] = current
    return arr

Java

java 复制代码
public class InsertSort implements IArraySort {

    @Override
    public int[] sort(int[] sourceArray) throws Exception {
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的
        for (int i = 1; i < arr.length; i++) {

            // 记录要插入的数据
            int tmp = arr[i];

            // 从已经排序的序列最右边的开始比较,找到比其小的数
            int j = i;
            while (j > 0 && tmp < arr[j - 1]) {
                arr[j] = arr[j - 1];
                j--;
            }

            // 存在比其小的数,插入
            if (j != i) {
                arr[j] = tmp;
            }

        }
        return arr;
    }
}

C++

c++ 复制代码
void insertion_sort(int arr[],int len){
        for(int i=1;i<len;i++){
                int key=arr[i];
                int j=i-1;
                while((j>=0) && (key<arr[j])){
                        arr[j+1]=arr[j];
                        j--;
                }
                arr[j+1]=key;
        }
}

Go

go 复制代码
func insertionSort(arr []int) []int {
        for i := range arr {
                preIndex := i - 1
                current := arr[i]
                for preIndex >= 0 && arr[preIndex] > current {
                        arr[preIndex+1] = arr[preIndex]
                        preIndex -= 1
                }
                arr[preIndex+1] = current
        }
        return arr
}

7. 折半插入排序

直接插入排序还可以通过二分算法优化性能,在排序元素数量较多时优化的效果比较明显。

时间复杂度:

折半插入排序与直接插入排序的基本思想是一致的,折半插入排序仅对插入排序时间复杂度中的常数进行了优化,所以优化后的时间复杂度仍然不变。

代码实现------C++

c++ 复制代码
void insertion_sort(int arr[], int len) {
  if (len < 2) return;
  for (int i = 1; i != len; ++i) {
    int key = arr[i];
    auto index = upper_bound(arr, arr + i, key) - arr;
    // 使用 memmove 移动元素,比使用 for 循环速度更快,时间复杂度仍为 O(n)
    memmove(arr + index + 1, arr + index, (i - index) * sizeof(int));
    arr[index] = key;
  }
}

结语

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!

带你初步了解排序算法:https://blog.csdn.net/2301_80191662/article/details/142211265

直接插入排序:https://blog.csdn.net/2301_80191662/article/details/142300973

希尔排序:https://blog.csdn.net/2301_80191662/article/details/142302553

十大经典排序算法总结与分析:https://blog.csdn.net/2301_80191662/article/details/142211564

相关推荐
jnrjian2 分钟前
USE_CONCAT in list OR 以及 filter Nest LOOP
数据结构·list
覆水难收呀5 分钟前
三、(JS)JS中常见的表单事件
开发语言·前端·javascript
阿华的代码王国9 分钟前
【JavaEE】多线程编程引入——认识Thread类
java·开发语言·数据结构·mysql·java-ee
繁依Fanyi15 分钟前
828 华为云征文|华为 Flexus 云服务器部署 RustDesk Server,打造自己的远程桌面服务器
运维·服务器·开发语言·人工智能·pytorch·华为·华为云
weixin_4866811431 分钟前
C++系列-STL容器中统计算法count, count_if
开发语言·c++·算法
基德爆肝c语言31 分钟前
C++入门
开发语言·c++
怀九日38 分钟前
C++(学习)2024.9.18
开发语言·c++·学习·面向对象·引用·
一道秘制的小菜39 分钟前
C++第七节课 运算符重载
服务器·开发语言·c++·学习·算法
易辰君1 小时前
Python编程 - 协程
开发语言·python
布洛芬颗粒1 小时前
JAVA基础面试题(第二十二篇)MYSQL---锁、分库分表!
java·开发语言·mysql