单向链表的快速排序实现

概览

上面一篇文章讲解了数组快速排序的实现,由于单向链表与数组天生差异,无法实现从后往前的指针遍历,所以考虑换一种方式来实现。

实现原理

既然不能从后往前进行指针遍历,那么就从前往后吧。同样的设定基准值pivot为链表的头结点的值,两个指针S(Small)和L(Large)分别指向头结点和头结点的next结点。我们的目标是保证S指针之前的元素都小于等于pivot,而S指针与L指针之间的数据都大与pivot,直到L指针指向最后一个结点。
判断L指向的结点的值是否大于pivot,如果否,则将S指针往后移动一个位置(我们一开始的目标就是S指针之前的结点值小于等于pivot,那么往后移动一个位置后的结点值必然大于pivot),交换S指针与L指针指向的结点的值,然后L指针往后移动;如果是,则只往后移动L指针,保持S指针不动。
不断进行以上操作,直到L指针指向链表最后一个结点。这时S指针之前(包括S指针指向的结点)的结点的值都小于等于pivot(不包括头结点,即设置pivot的结点),S指针和L指针之间的结点的值都大于pivot,然后交换S指针指向结点与头结点的值,完成一次排序。
再分别对(头结点-->Small指针指向的结点)以及(Small.next指针指向的结点-->尾结点)进行快速排序,最终得到完整链表的排序结果。

实现示例


实现代码

public class QuickSortLinkedList {
	private static int MAXNUM = 10;
	private static Node head = new QuickSortLinkedList.Node();
	//定义结点数据结构
	static class Node{
		public int value;
		public Node next;
	}
	
	/**
	 * 实现链表的快速排序算法
	 * @param head	链表的头结点
	 * @param end	链表的尾结点
	 */
	public static void quickSortLinkedList(Node head, Node end){
		if(head != end){	//链表至少需要两个结点,即头结点和尾结点不能相同
			int pivot = head.value;		//得到基准值
			Node small = head;		//small指针
			Node large = small.next;	//large指针
			
			while(large != end){	//如果large指针没有到尾结点
				if(large.value < pivot){	//如果large指向的结点值小于基准值,需要交换
					small = small.next;		//small指针后移
					if(small != large){		//如果不是指向同一个结点,则执行交换,否则不做处理
						int temp = small.value;
						small.value = large.value;
						large.value = temp;
					}
				}
				large = large.next;		//large指针后移
			}
			int temp = small.value;		//交换头结点和small指向的结点
			small.value = head.value;
			head.value = temp;
			
			quickSortLinkedList(head, small);	//对前半部分进行快速排序
			quickSortLinkedList(small.next, end);	//对后半部分进行快速排序
		}
	}
	
	public static void main(String[] args) {
		init(MAXNUM);	//初始化链表
		print();
		System.out.println();
		quickSortLinkedList(head, getEnd(head));
		print();
	}
	
	/**
	 * 链表初始化,每个结点的值随机生成为1-100之间
	 * @param n	链表的长度
	 */
	public static void init(int n){	
		Node current = head;
		for(int i = 0; i < n; i++){
			current.value = (int) (Math.random()*100 +1);	//结点的值随机为1-100之间
			current.next = new QuickSortLinkedList.Node();
			current = current.next;
		}
	}
	
	/**
	 * 链表的打印
	 */
	public static void print(){
		Node current = head;
		while(current.next != null){
			System.out.print(current.value + " ");
			current = current.next;
		}
	}
	
	/**
	 * 得到链表的最后一个结点
	 * @param head	链表的头结点
	 * @return	end 链表的尾结点
	 */
	public static Node getEnd(Node head){
		Node current = head;
		while(current.next != null){
			current = current.next;
		}
		Node end = current;
		return end;
	}

}





“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

zjuwill

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值