无序链表排序_双向链表排序算法

无序链表排序_双向链表排序算法需求给定一个无序的链表,输出有序的链表。分析链表排序比较特殊,由于不连续的性质,所以在进行排序的时候要引入外排思想,因此归并排序或者多路归并就成为了排序的选择。归并排序分为拆分、合并两个阶段:1.拆分需要拆分出链表中间节点,并赋值NULL阶段,形成两个独立的链表,直到拆分成单个节点为止。2.合并由于此时没个链表都为单节点,所以实质上是个有序链表合并问题。代码下面


Jetbrains全系列IDE稳定放心使用

需求

给定一个无序的链表,输出有序的链表。

分析

链表排序比较特殊,由于不连续的性质,所以在进行排序的时候要引入外排思想,因此归并排序或者多路归并就成为了排序的选择。
归并排序分为拆分、合并两个阶段:
1. 拆分
需要找出链表中间节点,并根据中间节点拆分成两个独立的链表,递归直到拆分成单个节点为止。
2. 合并
由于此时每个链表都为单节点,所以对于拆分的两个子链表实质上是有序链表合并问题。

代码

下面是示例代码

    private class Node {
        int value;
        Node next;
    }

    private Node getRandomList(int length)
    {
        Node node = new Node();
        int randomNum = (int) ((Math.random() * 100) % 100);
        node.value = randomNum;
        Node head = node;
        for(int i = 0; i < length; i++)
        {
            randomNum = (int) ((Math.random() * 100) % 100);
            Node temp = new Node();
            temp.value = randomNum;
            node.next = temp;
            node = temp;
        }

        return head;
    }

    private Node getMiddleNode(Node head)
    {
        Node index1 = head;
        Node index2 = head;
        while(index2.next != null && index2.next.next != null)
        {
            index1 = index1.next;
            index2 = index2.next.next;
        }

        return index1;
    }

    private Node mergeSort(Node head)
    {
        if(head.next == null)
            return head;

        Node middelNode = getMiddleNode(head);
        Node head1 = head;
        Node head2 = middelNode.next;
        middelNode.next = null;

        head1 = mergeSort(head1);
        head2 = mergeSort(head2);

        Node currenthead = mergeSequentialList(head1, head2);

        return currenthead;
    }

    private Node mergeSequentialList(Node head1, Node head2)
    {

        if(head1 == null)
            return head2;
        if(head2 == null)
            return head1;
        Node currentNode = null;
        if(head1.value < head2.value)
        {
            head1.next = mergeSequentialList(head1.next, head2);
            currentNode = head1;
        }
        else
        {
            head2.next = mergeSequentialList(head1, head2.next);
            currentNode = head2;
        }

        return currentNode;
    }

    private int outputListValue(Node list, StringBuffer bf) {
        // TODO Auto-generated method stub

        int i = 0;
        while(list.next != null)
        {
            bf.append(list.value + "-");
            i++;
            list = list.next;
        }
        return i;
    }


    public void main()
    {
        Node list = getRandomList(50);
        list = mergeSort(list);
        StringBuffer bf = new StringBuffer();
        int count = outputListValue(list, bf);
        String result = bf.toString();  
    }

复杂度

对于中间节点的查找,可以使用两指针不同步调方式,查找的时间复杂度为O(n)。
对于两个有序子链表合并,递归深度为最短链表深度,时间复杂度为O(n)。
由于归并排序会调用logn次,所以最终的时间复杂度为(2n)logn = O(nlogn)。

总结

无序链表排序考察的知识点比较多,首先要深刻理解归并排序的思想与应用场景,其次算法中也运用到了链表中间节点查找、两个有序链表归并等单算法,并且也要考虑单算法其中的细节。整体算法难度比较难。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183150.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm编写的文件如何执行_pycharm可以写java吗

    pycharm编写的文件如何执行_pycharm可以写java吗最近在做编译原理课设,准备用Java写个GUI整合一下,因为自己的LL1文法使用python写的,所以需要Java来实现运行python代码,网上给出了主要三种方法,但是使用Jython的方法有局限性且不太方便,于是我将采用最简洁的方法Runtime.getRuntime()运行python代码,下面给出代码Processproc;try{/*注意:这里这种方式和cmd中使用python+文…

    2022年8月27日
  • C语言十字相乘法_三次方十字相乘法

    C语言十字相乘法_三次方十字相乘法视频地址十字相乘法视频教程//初学C语言第2天,2小时写了一个简单的穷举法。#include<stdio.h>#include<math.h>intmain(){ intX=50;//自然数 floata,b,c; a=2;//二次项系数 b=5;//一次项系数 c=-3;//常数项 floata1,a2,a3,a4,…

    2022年11月2日
  • RNAseq-GO、biomaRt转换ID

    RNAseq-GO、biomaRt转换IDO.Sativa选用MSU或者RAPDB这两个数据库的genome和gtf文件,介绍一下MSU的ID,RAPDB的同理。TheRiceAnnotationProject(RAP)(https://rapdb.dna.affrc.go.jp/index.html)和RiceGenomeAnnotationProject(RGAP7,MSU)(http://rice.plantbiology.msu.edu/index.shtml)RAP格式为“Os-Chr-g-number”,MSU格式为“L

    2022年10月30日
  • navicat激活码2021【2021最新】

    (navicat激活码2021)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~DB…

    2022年3月26日
  • 浅析时序数据库评测和选型的区别_时序数据库 开源

    浅析时序数据库评测和选型的区别_时序数据库 开源时序数据库评测,时序数据库选型,松果时序数据库

    2022年10月4日
  • c# 基础语法

    c#基础语法基础语法第一个程序usingSystem;namespaceConsoleApp1{classProgram{staticvoidMain(string[]a

    2021年12月13日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号