算法学习——单链表快排

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

		if (start == null || start == end) {
			return;
		}
		Node last = start;
		Node cur = start.next;

		Node next ;

		// 1.默认start作为轴,如果index比start小则移动到start的next
		while (cur != null && cur != end) {
			next = cur.next;
			if (cur.value <= start.value) {
				if (start != last) {//为了防止第一个元素小于轴时发生的重复引用
					last.next = next;
					Node startNext = start.next;
					start.next = cur;
					cur.next = startNext;
					cur = next;
				}else{
					last = cur;
					cur = cur.next;
				}
			} else {
				last = cur;
				cur = cur.next;
			}
		}
		// 2.将轴移动到合适的位置,与小于轴的节点的值互换
		Node newIndex = start.next;
		last = start;
		// 找到轴插入的位置last,即找到最后一个小于轴的节点;newIndex != end是为了防止将end加入到计算范围中
		while (newIndex != null && newIndex != end && newIndex.value <= start.value) {
			last = newIndex;
			newIndex = newIndex.next;
		}
		//
		// 将轴与插入位置上节点的值进行交换
		int temp = last.value;
		last.value = start.value;
		start.value = temp;
		// 3.进行下一次迭代
		quickSortWithLinkedList(start, last);
		quickSortWithLinkedList(last.next, end);
	}
时间: 2024-12-29 23:52:43

算法学习——单链表快排的相关文章

单链表快排 改变节点位置

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

普林斯顿公开课 算法3-3:三路快排

很多时候排序是为了对数据进行归类,比如对城市进行排序,对员工的职业进行排序.这种排序的特点就是重复的值特别多. 如果使用普通的快排对这些数据进行排序,会造成N^2复杂度,但是归并排序和三路快排就没有这样的问题. 三路快排 三路快排的基本思想就是,在对数据进行分区的时候分成左中右三个部分,中间都是相同的值,左侧小于中间,右侧大于中间. 性能 三路快排的复杂度比普通快排小,主要取决于数据中重复数据的数量.重复数据越多,三路快排的复杂度就越接近于N. 代码 public class Quick3 {

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

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

数据结构之自建算法库——单链表

本文针对数据结构基础系列网络课程(2):线性表中第10课时单链表基本操作的实现,建立单链表数据存储结构基本操作的算法库. 按照"0207将算法变程序"[视频]部分建议的方法,建设自己的专业基础设施算法库. 单链表算法库算法库采用程序的多文件组织形式,包括两个文件: 1.头文件:linklist.h,包含定义顺序表数据结构的代码.宏定义.要实现算法的函数的声明: #ifndef LINKLIST_H_INCLUDED #define LINKLIST_H_INCLUDED typedef

链表快排

给定一个单向链表,在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/SysuJ

数据结构与算法学习-单向链表的实现

链表(Chain本文所说链表均为单向链表,以下均简称单向链表)实际上是由节点(Node)组成的,一个链表拥有不定数量的节点.而向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是直接或者间接地通过其头节点来进行的. 节点(Node)是由一个需要储存的对象及对下一个节点的引用组成的.也就是说,节点拥有两个成员:储存的对象.对下一个节点的引用. 这样说可能大家不是很明白,我贴一张图大家可能更容易理解. package LinkedList; /** * <p><strong>

算法数据结构 单链表的实现+操作 以及和顺序表的对比

顺序表和单链表的优缺点对比: 顺序表的优点,无需为表示表中元素之间的逻辑关系而增加额外的存储空间: 可以快速的存取表中的任意位置的元素. 顺序表的缺点,插入后删除操作需要移动大量元素: 当线性表长度不稳定时,存储空间难确定,容易造成存储空间碎片. 对于单链表 链式存储即元素存储的内存单元可以是不连续,分散的.对于元素间如何来维护他们的关系(即逻辑结构,每个元素的前驱和后继.) 即用到一个指针域来存储他和前驱或是后继直接的关系. 如上面的是一个单链表的指针结构,即每个元素中存储了他的后继元素的内存

C:数据结构与算法之单链表

单链表相对于顺序表比较难理解,但是比较实用,单链表的插入,删除不需要移动数据元素,只需要一个指针来寻找所需要的元素,还有一个大优点就是不浪费空间,当你想要增加一个结点可以申请(malloc())一个结点的空间,删除一个结点也可以释放(free()),跟顺序表一样的,首先先来定义一个单链表, 1 typedef struct lnode 2 { 3 int data; 4 struct lnode *next; 5 }LNode,*LinkList; typedef是将类型struct lnode

[算法]在单链表和双链表中删除倒数第k个结点

题目: 分别实现两个函数,一个可以删除单链表中倒数第K个节点,另一个可以删除双链表中倒数第K个节点. 要求: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1). 解答: 让链表从头走到尾,每移动一步,就让K值减一,当链表走到结尾时,如果K值大于0,说明不用调整链表,因为链表根本没有倒数第K个节点,此时将原链表直接返回即可:如果K值等于0,说明链表倒数第K个节点就是头结点,此时直接返回head.next,相当于删除了头结点.当K的值小于零时,再次从头结点开始走,每移动一步,就让