题目:使用插入排序对链表进行排序
题目理解:
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;
}