Leetcode打卡三:使用插入排序对链表进行排序。

题目:使用插入排序对链表进行排序

题目理解:

1.使用插入排序对链表排序,首先我们要很明白大概的一个思路,肯定是用一个新的空链表一个个的向里面进行添加元素
2.其次,对于新链表的使用,我这里提供两种不同的实现,一种是带头结点的,另一种是不带头结点的。这两种的区别其实还是挺大的,我第一次编写是使用了不带头结点的,然后看了不带头结点的写法,发现实在是太麻烦了。
3.对于遍历,外层遍历肯定是不用说了,遍历原有的链表,里层遍历就需要注意一些细节,比如如何做到最简单,我自己写的时候就没有做到很简单,实际上在里层遍历的时候,我们只需要找到要插入的节点前驱节点就可以了

不带头结点的实现:

我自己写的比较麻烦,不想看的可以不看,但是要明白不带头结点和带头结点的区别是什么:那就是要考虑链表的头是会改变的!就是要插入的地方可能是第一个节点!
实现步骤:
1.首先建立一个新的链表,将head的第一个值直接传进去
2.插入节点必须要前驱节点和后驱节点,所以需要p,q
3.由于没有头结点,所以需要定义一个listHead 来保存第一个节点,因为可能第一个节点是会改变的
4.判断有三种情况:
第一种:插在第一个节点的前面,这时候listHead 就要修改了
第二种:插在中间
第三种:插在链表末尾

public  static ListNode insertionSortList(ListNode head) {
    if(head == null) {
        return head;
    }
    int x = head.val;
    ListNode listNode = new ListNode(x);//将head的第一个节点直接传进去
    ListNode listHead = listNode;   //记录新链表的第一个结点
    ListNode q,p;// q为前驱节点  p为后驱节点 插入时需要用到
    head = head.next;//第一个已经可以不要遍历了 因为已经加进去了
    while(head != null){
        ListNode temp = new ListNode(head.val); //需要插入的节点
        q = listHead;//每次遍历都要从第一个节点遍历
        //判断是否要插在第一个结点前面,如果是的话listHead就要改变了
        if(head.val < q.val){ 
            temp.next = q;
            listHead = temp;
            head = head.next;
            continue;
        }
        while(q != null){
            if(q.next == null){//判断是否插在链表末尾
                q.next = temp;
                q = q.next;
                break;
            }
            p = q.next;
            if((head.val >= q.val) &&(head.val <= p.val)){ //判断是否插在中间
                temp.next = p;
                q.next =temp;
                q = q.next;
                break;
            }
            q = q.next;

        }
        head = head.next;
    }

    return listHead;
}

带头结点的实现:

这里就简单很多:
1.定义一个虚拟的头结点,这个头结点是永远不会变的,这就是和上面的区别
2.里层遍历每次都从虚拟的头结点开始遍历
3.里层遍历的作用是寻找到第一个比他大的节点,找到了就意味着要插在这个节点的前面,所以这里根本就没有if判断,这个while循环跳出的时候就已经找到要插入的位置了
4.最后我们只要返回头结点的next就可以了

public  static ListNode insertionSortList1(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode listNode = new ListNode(0);//虚拟头结点


        ListNode p,q;// p为前驱节点  q为后驱节点 插入时需要用到

        while(head != null){

            //每次遍历都是从头结点开始重新遍历 并且这个是永远不变的 这里就和不带头结点区别很大 方便很多
            //就不需要考虑是否头结点会改变
            p = listNode; //前驱节点
            q = p.next;  //比较(后驱)节点
            ListNode temp = new ListNode(head.val);

            //寻找第一个比他大的节点的 q,p
            while((q != null) && (q.val < temp.val)){
                p = p.next;
                q = q.next;
            }
            //经过上面的循环后 q指向的就是即将插入节点(temp)的后驱节点
            temp.next = q;
            p.next = temp;

            head = head.next;
            }
            return  listNode.next;

        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值