21天经典算法之直接插入排序


活动地址:CSDN21天学习挑战赛

专栏前言:

本专栏主要是算法训练,目的很简单。就是为了进厂
最近官方在组织 21 天挑战赛,趁此机会我也更新一下经典算法的文章
如果想一起“狂”或者交流,欢迎来私聊
还不快趁着这个机会来提升自己💪

👉排序算法介绍

排序算法是通过特定的算法因式将一组或多组数据按照既定模式进行重新排序。最终序列按照一定的规律进行呈现。

在排序算法中,稳定性和效率是我们经常要考虑的问题。

稳定性:稳定是指当两个相同的元素同时出现于某个序列之中,则经过一定的排序算法之后,两者在排序前后的相对位置不发生变化。

复杂度分析:
(1)时间复杂度:即从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。
(2)空间复杂度:就是从序列的初始状态经过排序移位变换的过程一直到最终的状态所花费的空间开销。

常见的排序算法分为以下几种:
在这里插入图片描述

👉直接插入排序

原理

输入一个元素,检查数组列表中的每个元素,将其插入到一个已经排好序的数列中的适当位置,使数列有序,当最后一个元素放入合适位置时,该数组排序完毕。

核心思想:将数组中的所有元素和依次已经排好的元素序列进行比较,如果选择的元素要比已排序的元素大(小),则交换,直到和全部元素都比较过。最终序列学列呈现上升或下降趋势。

代码实现

数组:nums[]
for(int i = 1; i < nums.length; ++i){
    int temp = nums[i], j = i - 1;
    while(j >= 0 && nums[j] > temp){
        nums[j + 1] = nums[j];
        j = j - 1;
    }
    nums[j + 1] = temp;
}

复杂度分析

时间复杂度

  • 最好的情况: O ( n ) O(n) O(n)。数组本身按照所需要的规则排序,那么就不需要移动任何元素,只需要将元素比较确保该元素站在序列中应该在的位置。那么执行次数只是一层循环,一共是 n − 1 n - 1 n1 次。所以最好情况下的时间复杂度为 O ( n ) O(n) O(n)
  • 最坏的情况: O ( n 2 ) O(n^2) O(n2)。当元素序列是按照所需规则的相反规则来排列的,也就是反向有序,那么每次取出的元素都需要和已经排好序的数列元素进行比较。那么最终代码执行的循环次数是 ∑ i = 1 k i = O ( n 2 ) \sum_{i=1}^{k}i=O(n^2) i=1ki=O(n2)
  • 平均复杂度: O ( n 2 ) O(n^2) O(n2)

空间复杂度 O ( 1 ) O(1) O(1)。算法在执行过程中需要一个辅助空间来保存比较元素,所以空间复杂度为 O ( 1 ) O(1) O(1)

👉示例:

在这里插入图片描述

👉算法实践

💭
算法的整体思想已经在上面讲述了,下面直接使用一个例子来试试水。在链表中应该如何操作

直接插入排序

题目描述:

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

插入排序 算法的步骤:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。
下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。

对链表进行插入排序。

在这里插入图片描述

示例 1:
在这里插入图片描述

输入: head = [4,2,1,3]
输出: [1,2,3,4]

示例 2:

在这里插入图片描述

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

提示:

列表中的节点数在 [1, 5000]范围内
-5000 <= Node.val <= 5000

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode insertionSortList(ListNode head) {
        if(head == null){
            return head;
        }
        ListNode temp = new ListNode(0);
        temp.next = head;

        //pre是已排序链表的最后一个节点,cur是待排序的链表
        ListNode pre = head, cur = head.next;

        while(cur != null){
            if(cur.val >= pre.val){  //后面的值>=前面的值
                pre = pre.next;
            }else{
                ListNode prev = temp;
                while(prev.next.val <= cur.val){
                    prev = prev.next;
                }
                //把前面的值和后面的进行交换
                pre.next = cur.next;
                cur.next = prev.next;
                prev.next = cur;
            }
            cur = pre.next;
        }
        return temp.next;
    }
}

👉课后习题

如果你觉得掌握了,那么赶快来实践一下吧

序号题目链接难度评级
1147. 对链表进行插入排序中等

评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秦 羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值