排序算法(五.插入排序2-二分插入排序和单链表插入排序)

本文详细介绍了二分插入排序和单链表直接插入排序的算法思想和Java实现。二分插入排序利用二分查找确定插入位置,而单链表插入排序需要从前往后遍历已排序部分,找到合适位置插入节点。对于单链表,还讨论了不同插入情况的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分插入排序

二分法插入排序,简称二分排序,是在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们中间的那个元素比,如果小,则对前半再进行折半,否则对后半进行折半,直到left<right,然后再把第i个元素前1位与目标位置之间的所有元素后移,再把第i个元素放在目标位置上。

算法思想

二分法没有排序,只有查找。所以当找到要插入的位置时。移动必须从最后一个记录开始,向后移动一位,再移动倒数第2位,直到要插入的位置的记录移后一位。
1、查找
二分法查找插入位置
如果R<R[m]成立,那右指针就要向左移动中间指针一位,否则,左指针要向右移动中间指针一位。反复查找,直到左指针大于右指针时停止。
2、后移
有点迷惑,什么时候需要后移呢?有哪些记录需要移动呢?
虽然我们很清楚的知道,我们需要后移那些排序码大于R的记录,但难免会问自己这样几个问题。其实它相当于需要移动从i-1到左指针的记录。
3、插入
由1中得到的左指针其实就是元素要插入的位置。

Java实现

/**
 * 二分插入排序
 *
 * @param nums
 * @return
 */
public static int[] binaryInsertSort(int[] nums){
    if(null == nums || nums.length == 0){
        System.out.println("输入的数组为空!");
        return null;
    }
    for (int i = 1; i < nums.length; i++) {
        int temp = nums[i];
        int low = 0, high = i - 1;
        int mid = -1;
        while (low <= high) {
            mid = low + (high - low) / 2;
            if (nums[mid] > temp) {
                high = mid - 1;
            } else { // 元素相同时,也插入在后面的位置
                low = mid + 1;
            }
        }
        for(int j = i - 1; j >= low; j--) {
            nums[j + 1] = nums[j];
        }
        nums[low] = temp;
    }
    return nums;
}

单链表直接插入排序

算法描述

单链表插入排序和数组插入排序的不同:数组插入排序是从排好序的部分的最后一个节点往前找,找到第一个比它小的数,然后插到其后面;而单链表只能从前往后遍历,找到第一个比当前节点大的值结束,因此在遍历已经排好序的链表部分的时候,需要两个指针,一个指针用于往前遍历(该指针假设为遍历指针),一个指针用于记录遍历指针指向的当前节点的前一个节点(该指针假设为遍历指针),这样当遍历指针找到第一个比待插入节点的值大的节点的时候,就可以将待插入节点插入到记录指针的后面。(之所以使用两个指针,是因为单链表不能反指)
插入排序分两种情况,一种是当前节点的值比已经排好序的尾节点的值大,则直接将当前节点挂在已排序的节点即可;一种是当前节点值比已经排好序的尾节点的值小,则需将已排好序的链表部分从头到尾遍历,找到第一个比当前节点值大的节点,插入到其前面即可。因为可能待插入的节点可能在第一个节点的前面,因此另外创建一个头结点,指向已经排好序的链表的第一个节点。这样可以每次插入新的节点的时候,将上面所提到的记录节点初始化为新创建的头结点,这样便于在第一个节点前面插入新节点。

Java实现

单链表的实现在此不赘述,有想了解的朋友可以查看https://blog.youkuaiyun.com/u014229347/article/details/88966409

/**
 * <p>@filename SingleLinkedListInsertSort</p>
 * <p>
 * <p>@description 单链表直接插入排序</p>
 *
 * @author Java猿人一枚
 * @version 1.0
 * @since 2019/4/1 16:42
 **/
public class SingleLinkedListInsertSort {

    public static void main(String[] args) {
        int[] nums = new int[]{100,34,52,6,8,78,95};
        SingleLinkedList<Integer> singleLinkedList = new SingleLinkedList<>();
        for (int i = 0; i < nums.length; i++) {
            singleLinkedList.addNode(nums[i], i);
        }
        System.out.print("排序前:");
        singleLinkedList.print();
        System.out.println();
        singleLinkedList = singleLinkedListInsertSort(singleLinkedList);
        System.out.print("排序后:");
        singleLinkedList.print();
    }

    /**
     * 单链表插入排序
     *
     * @param singleLinkedList
     * @return
     */
    public static SingleLinkedList<Integer> singleLinkedListInsertSort(SingleLinkedList<Integer> singleLinkedList){
        SingleLinkedList.Node<Integer> head = singleLinkedList.getHead();
        if(head == null || head.next == null){
            return singleLinkedList;
        }else{
            SingleLinkedList<Integer> newSingleLinkedList = new SingleLinkedList<>();
            newSingleLinkedList.addHead(head.value);
            while(head.next != null){
                head = head.next;
                SingleLinkedList.Node<Integer> newHead = newSingleLinkedList.getHead();
                for (int i = 0; i < newSingleLinkedList.size(); i++){
                    if(head.value < newHead.value){
                        newSingleLinkedList.addNode(head.value, i);
                        newSingleLinkedList.print();
                        System.out.println();
                        break;
                    }else{
                        newHead = newHead.next;
                    }
                }
            }
            singleLinkedList = newSingleLinkedList;
        }
        return singleLinkedList;
    }
}

以上代码均为个人实现,有问题欢迎一起交流探讨!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值