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

快速排序的链表实现

算法思想:对于一个链表,以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. 【linux】mysql安装问题 g++: not found

    问题现象: ../depcomp: line 512: exec: g++: not foundmake[2]: *** [my_new.o] Error 127make[2]: Leaving di ...

  2. mkfs -t ext3 错误/dev/sdxx is apparently in use by the system; 解决方法

     在存储上共享了一个500G的空间,映射到Linux系统提供上,环境由2个节点组成. 一. 测试一: 直接mount 用fdisk 格式化之后如下: [root@rac1 u01]# fdisk ...

  3. but the supplied types were (flex.messaging.io.amf.ASObject) and converted to (null)."

    1.错误描述 [RPC Fault faultString="Cannot invoke method  'saveOrUpdate'. " faultCode="Ser ...

  4. pat1121-1131

    1121 #include<cmath> #include<map> #include<iostream> #include<cstring> #inc ...

  5. 认识大前端html+css+js

    认识大前端:前端就是将效果图生成网页,利用html+css+js等技术. 如果把前端比作一台汽车,那么html就是车的骨架,css就是完整的车的模型,而js就充当着车的发动机... 建议:   刚刚开 ...

  6. 【BZOJ3670】动物园(KMP算法)

    [BZOJ3670]动物园(KMP算法) 题面 BZOJ 题解 神TM阅读理解题 看完题目之后 想暴力: 搞个倍增数组来跳\(next\) 每次暴跳\(next\) 复杂度\(O(Tnlogn)\) ...

  7. Bzoj4869: [Shoi2017]相逢是问候

    题面 传送门 Sol 摆定理 \[ a^b\equiv \begin{cases} a^{b\%\phi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~ ...

  8. Heavy Transportation POJ - 1797

    题意 给你n个点,1为起点,n为终点,要求所有1到n所有路径中每条路径上最小值的最最值. 思路 不想打最短路 跑一边最大生成树,再扫一遍1到n的路径,取最小值即可,类似Frogger POJ - 22 ...

  9. javascript DOM操作 节点的遍历

    通过javascript的遍历可以由一个节点来查找它的子节点(childNodes).兄弟节点(nextSibling/previousSibling)和父节点(parentNode). 代码说明: ...

  10. c++ 指针总结 函数参数指针调用和堆栈内存的分配原理

    c++中的char指针 这个char指针很有意思,char指针通常有两种初始化形式.一个是使用char数组初始化,一个是使用char变量初始化. c++当中使用双引号括起来的字符串起始已经被编译器初始 ...