链表----插入、归并、快速排序

1、插入排序

思路:外循环保证元素的逐个插入,不用考虑是否断裂,内循环根据找个要插入元素的前一个节点,然后把待插入的节点放进去,修改两个指针即可。

//1 插入排序N*N
    public static ListNode sortList1(ListNode head) {
        if (head == null) return head;
        ListNode helper = new ListNode(0);
        while (head != null) {
            ListNode temp = head.next;
            ListNode node = helper;
            while (node.next != null && node.next.val < head.val) node = node.next;
            head.next = node.next;
            node.next = head;
            head = temp;
        }
        return helper.next;
    }

2、归并排序

思路:找到链表的中间节点,把链表断开成两段,然后两段递归,返回两段的合并

使用归并排序     使用Merge Sort, 空间复杂度是 O(logN) 因为使用了栈空间
public ListNode sortList(ListNode head) { 
        // write your code here
        if (head == null || head.next == null) {
            return head;
        }
        ListNode slow = head;
        ListNode fast = head.next.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode head2 = sortList(slow.next);
        slow.next = null;
        ListNode head1 = sortList(head);
        return mergeSorted(head1,head2);
    }

    public ListNode mergeSorted(ListNode h1,ListNode h2) {
        ListNode dummy = new ListNode(-1);
        ListNode p = dummy;
        while (h1 != null && h2 != null) {
            if (h1.val < h2.val) {
                p.next = h1;
                h1 = h1.next;
            } else {
                p.next = h2;
                h2 = h2.next;
            }
            p = p.next;
        }
        if (h1 != null) {
            p.next = h1;
        }
        if (h2 != null) {
            p.next = h2;
        }
        return dummy.next;
    }

3、快速排序

思路:

- 使第一个节点为中心点

- 创建2个指针(p,q),p指向头结点,q指向p的下一个节点

- q开始遍历,如果发现q的值比中心点的值小,则此时p=p->next,并且执行当前p的值和q的值交换,q遍历到链表尾即可

- 把头结点的值和p的值执行交换。此时p节点为中心点,并且完成1轮快排

- 使用递归的方法即可完成排序

方式一:通过交换节点的值来实现

public ListNode sortList(ListNode head) {
        // write your code here
        ListNode tail = head;
        while (tail != null && tail.next!= null) {
            tail = tail.next;
        }
        quick_sort(head,tail);
        return head;
    }


    public void quick_sort(ListNode start,ListNode end) {
        if (start == null || end == null || start == end) {
            return;
        }
        ListNode slow = start;
        ListNode fast = start.next;
        int base = start.val;
        while (fast != end.next && fast != null) {
            if (fast.val < base) {
                slow = slow.next;
                if (slow != fast) {
                    int temp = slow.val;
                    slow.val = fast.val;
                    fast.val = temp;
                }
            }
            fast = fast.next;
        }
        if (start != slow) {
            int temp = slow.val;
            slow.val = start.val;
            start.val = temp;
        }
        quick_sort(start,slow);
        quick_sort(slow.next,end);
    }

方式二,通过交换节点来实现

一次遍历把链表分成三段,第一段都是比所选分界点值小的,第二段是值和分界点值相等的,第三段是比分界点值大的,然后合并三段即可

public ListNode sortList(ListNode head) {
        // write your code here
        if (head == null || head.next == null) {
            return head;
        }
        ListNode left = new ListNode(-1);
        ListNode mid = new ListNode(-1);
        ListNode right = new ListNode(-1);
        ListNode lefthead = left;
        ListNode midhead = mid;
        ListNode righthead = right;
        int base = head.val;
        ListNode p = head;
        while (p != null) {
            if (p.val < base) {
                left.next = p;
                left = left.next;
            } else if (p.val > base) {
                right.next = p;
                right = right.next;
            } else {
                mid.next = p;
                mid = mid.next;
            }
            p = p.next;
        }
        left.next = null;
        mid.next = null;
        right.next =null;
        return merge(sortList(lefthead.next),midhead.next,sortList(righthead.next));
    }
    public ListNode merge(ListNode first,ListNode mid,ListNode end) {
        ListNode res = null;
        //判断是否有第一段
        if (first != null) {
            res = first;
            ListNode tail = findtail(first);
            tail.next = mid;
        } else {
            res = mid;
        }
        //拼接后半段
        ListNode midtail = findtail(mid);
        midtail.next = end;
        return res;
    }
    public ListNode findtail(ListNode head) {
        while (head != null && head.next != null) {
            head = head.next;
        }
        return head;
    }

猜你喜欢

转载自blog.csdn.net/l1394049664/article/details/81350229