上篇博客中讲解了九大内部排序算法,部分算法还提供了代码实现,但是那些代码实现都是基于数组进行排序的,本篇博客就以链表排序实现几种常见的排序算法,以飨读者。

快速排序的链表实现

算法思想:对于一个链表,以head节点的值作为key,然后遍历之后的节点,可以得到一个小于key的链表和大于等于key的链表;由此递归可以对两个链表分别进行快速。这里用到了快速排序的思想即经过一趟排序能够将小于key的元素放在一边,将大于等于key的元素放在另一边。

代码实现:

     //快速排序
public static void quickSort(ListNode begin, ListNode end){
if(begin == null || begin == end)
return; ListNode index = paration(begin, end);
quickSort(begin, index);
quickSort(index.next, end);
} /**
* 划分函数,以头结点值为基准元素进行划分
* @param begin
* @param end
* @return
*/
public static ListNode paration(ListNode begin, ListNode end){
if(begin == null || begin == end)
return begin; int val = begin.val; //基准元素
ListNode index = begin, cur = begin.next; while(cur != end){
if(cur.val < val){ //交换
index = index.next;
int tmp = cur.val;
cur.val = index.val;
index.val = tmp;
}
cur = cur.next;
} begin.val = index.val;
index.val = val; return index;
}

归并排序的链表实现

算法思想:单链表与数组相比只能顺序访问每个元素,因此在使用二路归并排序时关键在于找到链表的中间结点将链表一分为二:可以利用快慢指针同时遍历单链表,当步长为2的指针指向链表最后一个结点或者最后一个结点的下一个结点时,步长为1的指针即指向链表的中间结点。然后是两个有序单链表的合并问题。时间复杂度为O(N*logN),空间复杂度为O(1)。

代码实现:

     //归并排序
public static ListNode mergeSort(ListNode head){
if(head == null || head.next == null) //空链表或者只有单个结点
return head;
ListNode slow = head, fast = head.next; while(fast != null && fast.next != null){ //使用快慢指针寻找中间 结点
slow = slow.next; fast = fast.next;
if(fast.next != null)
fast = fast.next;
} ListNode ptr1 = slow.next;
slow.next = null; ListNode tmp1 = mergeSort(head);
ListNode tmp2 = mergeSort(ptr1);
return merge(tmp1, tmp2);
} public static ListNode merge(ListNode start1, ListNode start2){
ListNode header = new ListNode(-1);
ListNode pre = header; ListNode ptr1 = start1, ptr2 = start2;
while(ptr1 != null && ptr2 != null){
if(ptr1.val <= ptr2.val){
pre.next = ptr1;
pre = ptr1;
ptr1 = ptr1.next;
}else{
pre.next = ptr2;
pre = ptr2;
ptr2 = ptr2.next;
}
}
while(ptr1 != null){
pre.next = ptr1;
pre = ptr1;
ptr1 = ptr1.next;
} while(ptr2 != null){
pre.next = ptr2;
pre = ptr2;
ptr2 = ptr2.next;
} return header.next; }

冒泡排序的链表实现

算法思想:依次比较相邻的结点,如果是逆序的就交换两个结点

代码实现:

     //冒泡排序
public static ListNode bubbleSort(ListNode head){
if(head == null || head.next == null) //链表为空或者仅有单个结点
return head; ListNode cur = null, tail = null; cur = head; while(cur.next != tail){
while(cur.next != tail){
if(cur.val > cur.next.val){
int tmp = cur.val;
cur.val = cur.next.val;
cur.next.val = tmp;
}
cur = cur.next;
} tail = cur; //下一次遍历的尾结点是当前结点(仔细琢磨一下里面的道道)
cur = head; //遍历起始结点重置为头结点
} return head; }

先写这几种吧,想起来再更。。。

 

常见的链表排序(Java版)的更多相关文章

  1. c++复杂桶排序Java版

    c++复杂桶排序Java版 题目和我的前几个排序一样 这次是Java版的 代码 + 注释 package com.vdian.qatest.supertagbiz.test.niu; /** * Cr ...

  2. 算法练习5---快速排序Java版

    基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成 ...

  3. 常见机试题分析Java版

    1. 操作系统任务分为系统任务和用户任务两种.其中,系统任务的优先级<50,用户任务的优先级>=50且<=255.优先级大于255的为非法任务,应予以剔除.现有一任务队列task[] ...

  4. 选择排序Java版

    package dataStructureAlgorithmReview.day01; import java.util.Arrays; /** * * @author shundong * */ p ...

  5. 南阳ACM 题目8:一种排序 Java版

    一种排序 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复:还知道这个长方形的宽和长,编号.长.宽都是整数:现 ...

  6. 算法练习4---冒泡排序java版

    冒泡排序的基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒.即:每当两相邻的数比较后发现它们的排序与排序要求相反 ...

  7. 算法练习1---桶排序java版

    今天复习了桶排序. 例如现在有满分为10分的试卷,学生得分分别为2,8,5,3,5,7,现在要给这些分数按照从大到小输出,使用桶排序的思想:有11个桶,每个桶有一个编号,编号从0-10,每出现一个分数 ...

  8. 剑指offer第二版面试题5:从尾到头打印链表(JAVA版)

    题目描述: 输入一个链表,从尾到头打印链表每个节点的值.返回新链表. import java.util.Stack; //定义链表结构 class ListNode { int value; List ...

  9. 《剑指offer》面试题13 在O(1)时间删除链表节点 Java版

    这道题的关键是知道找到尾节点的前一个节点必须遍历,而且这样做了之后总的时间复杂度还是O(1),以及如何不破坏链表删除一个已知节点 public ListNode delete(ListNode hea ...

随机推荐

  1. TOE(TCP/IP Offload Engine)网卡与一般网卡的区别

    TCP减压引擎,第一次听说这个名词,但是并不是一个新的概念了,若干年前听说过设备厂商在研究在FPGA之中实现TCP Stack,但是后来没有听到任何的产品出来,应该是路由设备to host的traff ...

  2. 如何修改WinPE Boot的.wim镜像文件

    1. 使用imagex /apply或imagex /mountrw将WIM镜像文件mount到某个文件夹,假设为d:\tmp\winpe_x86\mount.  例: imagex /mountrw ...

  3. 图像处理------颜色梯度变化 (Color Gradient)

    有过UI设计经验的一定对2D图形渲染中的Color Gradient 或多或少有些接触,很多编程 语言也提供了Gradient的接口,但是想知道它是怎么实现的嘛? 本文介绍三种简单的颜色梯度变化算法, ...

  4. 挖一挖不常用到而又很实用的重载-Split

    Split这个基本上所有的程序开发人员都用到,一般使用单字符和长字符串拆分字符串的较多,其实还有一个重载非常好用,那就是多种组合字符来进行拆分. 例如: "aaaaaaaaaa{@}bbbb ...

  5. Caused by: Unable to locate parent package [json-default] for [class com.you.user.action.StudentActi

    1.错误描述 信息: Choosing bean (struts) for (com.opensymphony.xwork2.util.TextParser) 2014-7-13 1:52:04 or ...

  6. 异常-----freemarker.core.ParseException: Token manager error

    一,案例一 1.1.错误描述 freemarker.core.ParseException: Token manager error: freemarker.core.TokenMgrError: L ...

  7. 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(3)

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 由于 ...

  8. RobotFramework下的http接口自动化Get关键字的使用

    在使用Create Http Context关键字创建了http的调用环境后,就可以使用Get关键字来发送一个http协议中最常用的get请求了. Get 关键字只接受一个url参数,该关键字的API ...

  9. jquery 实现一个简单的成功提示框,失败提示框

    主要的jquery代码:var TS={ successAlert:function(str){ //调用成功的方法 var html='<div class="alert alert ...

  10. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...