链表——单链表的排序

题目要求:

对单链表进行从小到大排序,要求时间复杂度O(N*logN),空间复杂度O(1);

思路:

因时间复杂度要求为O(N*logN),简单排序(时间复杂度为O(N*N))均不可用,

故可以考虑归并排序的思想,归并排序对数组操作空间复杂度为O(n),但对链表为O(1),因为每次只在merge函数中创建了一个辅助的链表头结点ListNode temp=new ListNode(0);

归并排序的一般步骤为:

1)将待排序数组(链表)取中点并一分为二;

2)递归地对左半部分进行归并排序;

3)递归地对右半部分进行归并排序;

4)将两个半部分进行合并(merge),得到结果。

所以对应此题目,可以划分为三个小问题:

1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);

2)写出merge函数,即如何合并链表。

3)写出mergesort函数,实现上述步骤。

代码如下:

/*
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode sortList(ListNode head) {
        //mergesort 空间复杂度为1;
        if(head==null||head.next==null)
            return head;

        ListNode mid=findMid(head);
        ListNode left=head;
        ListNode right=mid.next;

        mid.next=null;

        left=sortList(left);
        right=sortList(right);

        head=merge(left,right);

        return head;
    }

   //若链表节点为奇数,则找到中间节点;若链表节点为偶数,则找到两个中间节点的前一个;
 public ListNode findMid(ListNode head)
     {
     ListNode prear=head;
     ListNode pfront=head;
     while(prear.next!=null&&prear.next.next!=null)
         {
         prear=prear.next.next;
         pfront=pfront.next;
     }
     return pfront;
 }

    public ListNode merge(ListNode left,ListNode right)
        {
        if(left==null)
            return right;
        if(right==null)
            return left;
    //相较数组,并没有辅助数组的赋值操作,空间复杂度为O(1);
        ListNode temp=new ListNode(0);
        ListNode p=temp;

        while(left!=null&&right!=null)
            {
            if(left.val<right.val)
                {
                p.next=left;
                p=p.next;
                left=left.next;
            }else
                {
                p.next=right;
                p=p.next;
                right=right.next;
            }
        }
        if(left!=null)
            {
            p.next=left;
        }
        if(right!=null)
            {
            p.next=right;
        }

        return temp.next;
    }
}

时间: 2024-12-14 10:45:29

链表——单链表的排序的相关文章

链表 单链表反转

思路1:O(n^2). “狸猫换太子”,不进行改动链表结构,只首尾交换len/2次.但是在本函数中用到了定位函数,定位函数实际上是遍历了一遍整个链表,所以综合效率很低,达到O(n^2). //单链表反转(O(n^2)) void reverseList(Node* Head) { int count = numOfNodes(Head); //首尾交换 for(int i=1; i<=count/2; i++) { Node* p1 = locateNodeI(Head, i); Node* p

链表-单链表的各种操作

单链表的结构体的定义 typedef struct LNode { ElemType data; struct LNode *next; }LinkList; 基本的单链表的操作 /* 功能:构建一个空的带头节点的单链表*/ Status InitList (struct LNode **L) { (*L) = (struct LNode *)malloc(sizeof(struct LNode)); //产生头节点 if(!*L) exit(OVERFLOW); (*L)->next = NU

链表 - 单链表逆序

单链表逆序是经典的链表操作算法,单链表逆序的算法思想是将链表箭头反指(假设next指针是一个箭头),即所谓的改链,改链过程如下. 逆序前: head-->......prev-->cur-->next-->......->NULL 逆序后: NULL<--......prev<--cur<--next<--......head 算法逻辑: 1.空链表或只有一个元素,返回原链表head. 2.定义3个指针prev.cur.next,初始化时,prev指向

链表—单链表

代码实现: 首先定义一个Node类: public class Node { protected Node next; //指针域 public int data;//数据域 public Node( int data) { this. data = data; } //显示此节点 public void display() { System. out.print( data + " "); } } 接下来定义一个单链表,并实现相关方法: public class LinkList {

【数据结构】线性链表(单链表)

// // main.cpp // LinkList // // Created by T.P on 2019/1/31. // Copyright ? 2019 T.P. All rights reserved. // #include <stdio.h> #include <stdlib.h>//malloc free #define TRUE 1 #define FALSE 0 #define OK 0 #define ERROR -1 #define INFEASIBLE

数据结构 线性结构(数组[列表] ,链表 单链表的增删改查**, 线性结构的应用 队列 栈[函数的调用**]),非线性结构 树

数据结构 参考:http://lupython.gitee.io/ 线性结构 就是能够用一根线串起来的数据结构 数组 (列表) 问:申请数组的前提条件是啥? a[12]?内存需要满足的条件? 答:内存必须有一块连续的内存空间 int a[7] : 声明一个数组,这个数组的数组名是 a, 数组的大小是 7, 数组元素的类型是整型. int a[7] = array(1,2,3,4,5,6,7) 问:如何申请内存? 答:C,C++语言,申请:mallco (28).释放:free(28) 问:int

数据结构之链表---单链表的实现

public class Link { /** * 链结点 */ private int iData; private double dData; public Link next; public Link(int iData,double dData) { this.dData = dData; this.iData = iData; } //打印节点 public void displayLink() { System.out.println("{"+iData+",&q

leetcode之链表-单链表反转-C++

ReverseLinked List A linked list can be reversed eitheriteratively or recursively. Could you implement both? 迭代版本: 1. /** 2. * Definition for singly-linked list. 3. * struct ListNode { 4. * int val; 5. * ListNode *next; 6. * ListNode(int x) : val(x),

韩顺平_PHP程序员玩转算法公开课(第一季)02_单链表在内存中存在形式剖析_学习笔记_源代码图解_PPT文档整理

文西马龙:http://blog.csdn.net/wenximalong/链表——最灵活的数据结构链表用来解决复杂的问题和算法是很方便的. 内容介绍1.什么是链表2.单向链表3.双向链表4.环形链表5.使用环形链表解决约瑟夫问题 链表——什么是链表链表是有序的列表,但是它在内存中是分散存储的. 链表无处不在,比如在操作系统中,文件和文件之间,文件块和文件块之间,是靠链表链接起来的.使用链表可以解决类似约瑟夫问题,排序,索引,二叉树,广义表... 链表——单链表的快速入门使用head头的单向链表