链表快排

给定一个单向链表,在O(1)空间复杂度和O(nlogn)时间复杂度下进行排序

# -*- coding: utf-8 -*-
# @Time         : 2019-04-19 20:07
# @Author       : Jayce Wong
# @ProjectName  : job
# @FileName     : linkedListQuickSort.py
# @Blog         : https://blog.51cto.com/jayce1111
# @Github       : https://github.com/SysuJayce

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def linkedListQuickSort(head):
    sort_helper(head, None)
    return head

def sort_helper(head, end):
    """
    快排本质上来讲就是选择一个主元,比主元小的值都放到主元左边(以升序为例),其他都放到右边
    因此不论是数组还是链表,快排的递归代码是一样的
    """
    # 由于我们这里判断了head是否和end相等来作为递归的出口,因此不必向数组那样判断下标起止点的大小
    # 来作为递归出口
    if head != end:
        pivot = quick_sort(head)
        sort_helper(head, pivot)
        sort_helper(pivot.next, end)

def quick_sort(head):
    # 由于在链表中我们不能像数组那样选择一个下标来作为主元位置,因此就选择待排序链表的第一个元素作
    # 为主元即可。
    fast, slow = head.next, head  # slow是用来标记比主元小的元素应在的位置,fast用来遍历
    while fast:
        # 当发现有元素比主元(head)的值小的时候,我们先确定这个元素应该在的节点,然后将当前节点
        # 的值和应该在的节点的值交换
        if fast.val < head.val:
            slow = slow.next
            slow.val, fast.val = fast.val, slow.val

        fast = fast.next

    # 最后将主元的值放到正确的节点上
    slow.val, head.val = head.val, slow.val
    # 返回主元所在的节点
    return slow

def main():
    head = ListNode(3)
    head.next = ListNode(4)
    head.next.next = ListNode(2)
    head.next.next.next = ListNode(5)

    head = linkedListQuickSort(head)
    while head:
        print(head.val)
        head = head.next

if __name__ == ‘__main__‘:
    main()

原文地址:https://blog.51cto.com/jayce1111/2381665

时间: 2024-12-25 21:36:26

链表快排的相关文章

算法学习——单链表快排

/**  * 以p为轴对start-end间的节点进行快排(包括start && 不包括end):  * 思路:  * 1.将头节点作为轴节点start,从start.next开始遍历,如果节点小于轴start的值,将该节点插入到轴节点后面:  * 2.将轴节点插入合适位置,即找到最后一个小于轴的节点,将该节点与轴节点值互换,此时就链表分为两部分,小于轴节点和大于轴节点:  * 3.递归的遍历2中两部分节点.  *   * @param p  * @param start  * @para

链表快排 &amp; 基于链表的排序

以前只知道链表做插入(朴素.非二分)排序挺方便的.现在知道了(单)链表进行快速排序也是很好的(只是跟一般的快排的方式不一样). 参考: http://blog.csdn.net/otuhacker/article/details/10366563 我们只需要两个指针p和q,这两个指针均往next方向移动,移动的过程中保持p之前的key都小于选定的key,p和q之间的key都大于选定的key,那么当q走到末尾的时候便完成了一次支点的寻找.如下图所示:

单链表快排 改变节点位置

快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1)) 这里的partition,我们选取第一个节点作为枢纽元,然后把小于枢纽的节点放到一个链中,把不小于枢纽的及节点放到另一个链中,最后把两条链以及枢纽连接成一条链. 这里我们需要注意的是,1.在对一条子链进行partition时,由于节点的顺序都打乱了,所以得保正重新组合成一条新链表时,要和该子链表的前后部分连接起来,因此我们的partition传入三个参数,除了子链表的范围(也是前闭后开区间)

数据结构-链表快排

1 #include<cstdio> 2 #include<cstdlib> 3 #include<string> 4 5 struct Node{ 6 int num; 7 Node* next; 8 }; 9 10 void Add(Node **head, int num){ 11 Node *node = new Node; 12 node->num = num; 13 node->next = *head; 14 (*head) = node; 1

单链表的排序(快排和冒泡实现)以及查找中间结点

//快排,冒泡链表排序 #include<iostream> #include<assert.h> using namespace std; template<class T> struct LinkNode { T _data; LinkNode* _next; LinkNode(const T& x) :_data(x) , _next(NULL) {} }; template<class T> class ListNode { //为了安全性

待字闺中之快排(QuickSort)单向链表(Singly Linked List)

题目来源,待字闺中,原创@陈利人 ,欢迎大家继续关注微信公众账号"待字闺中" 分析:思路和数据的快速排序一样,都需要找到一个pivot元素.或者节点.然后将数组或者单向链表划分为两个部分,然后递归分别快排. 针对数组进行快排的时候,交换交换不同位置的数值,在分而治之完成之后,数据就是排序好的.那么单向链表是什么样的情况呢?除了交换节点值之外,是否有其他更好的方法呢?可以修改指针,不进行数值交换.这可以获取更高的效率. 在修改指针的过程中,会产生新的头指针以及尾指针,要记录下来.在par

63.如何对单链表进行快排?和数组快排的分析与对比[quicksort of array and linked list]

[本文链接] http://www.cnblogs.com/hellogiser/p/quick-sort-of-array-and-linked-list.html [题目] 单链表的特点是:单向.设头结点位head,则最后一个节点的next指向NULL.如果只知道头结点head,请问怎么将该链表排序? [分析] 对于数组的快排:有2种方式. (1)指针相向移动:一个指针i指向头,一个指针j指向尾,然后两个指针相向运动并按一定规律交换值,最后找到一个支点p使得支点左边的值小于支点,支点右边的值

C语言实现单向链表及其各种排序(含快排,选择,插入,冒泡)

#include<stdio.h> #include<malloc.h> #define LEN sizeof(struct Student) struct Student //结构体声明 { long num; int score; struct Student* next; }; int n; struct Student* creat() //创建单向链表 { struct Student *head=NULL, *p_before, *p_later; p_before =

排序(一)归并、快排、优先队列等

排序(一) 初级排序算法 选择排序 思想:首先,找到数组中最小的那个元素.其次,将它和数组的第一个元素交换位置.再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置.如此往复,直到将整个数组排序. [图例] 图中,x轴方向为数组的索引,y轴方向为待排序元素的值. 选择排序有两个很鲜明的特点: 运行时间和输入无关.为了找出最小的元素而扫描一遍数组并不能为下一遍扫描提供什么信息.这种性质在某些情况下是缺点.(无论数组的初始状态是什么,此算法效率都一样低效) 数据移动是最少的.每次交换都