链表排序(冒泡、选择、插入、快排、归并)的Java实现

文章来源:http://www.cnblogs.com/TenosDoIt/p/3666585.html

排序问题是code界老生常谈的话题了。
总结一下,主要有两种数据结构上的排序:数组、链表
数组的常用排序算法及实例戳这里:数组的七种经典排序算法Java实现
本文是对链表的常用排序算法的示例,当然也是Java实现。

“Speaking is easy, Show me the code 啊啊啊啊”

好好好,话不多说,上代码:

Java代码

下面的这份代码是可以直接拷贝到你的eclipse中运行的。是一份完整的例子。
你可以运行,感受下。

package leetcode;

public class ListNodeSorts {

	/**
	 * 定义的节点类
	 * @author fxjzzyo
	 *
	 */
	static class ListNode{
		int val;
		ListNode next;
		ListNode(int val){this.val = val;}
	}
	
	/**
	 * 交换两个节点的值
	 * @param i
	 * @param j
	 */
	public static void swap(ListNode i,ListNode j){
		int temp = i.val;
		i.val = j.val;
		j.val = temp;
	}
	
	/**
	 * 冒泡排序
	 * @param head
	 * @return
	 */
	public static ListNode bubbleSort(ListNode head){
		if(head == null || head.next == null) return head;
		ListNode p = null;
		
		boolean isExchanged = true;
		while(isExchanged&&p!=head.next){
			
			ListNode q = head;
			isExchanged = false;
			for(;q.next!=null&&q.next!=p;q = q.next){
				if(q.val>q.next.val){
					int temp = q.val;
					q.val = q.next.val;
					q.next.val = temp;
					isExchanged = true;
				}
			}
			p = q;
		}
		return head;
	}
	
	/**
	 * 插入排序
	 * 插入排序(算法中是直接交换节点,时间复杂度O(n^2),空间复杂度O(1))
	 * @param head
	 * @return
	 */
	public static ListNode insertSort(ListNode head){
		if(head == null || head.next == null) return head;
		ListNode pStart = new ListNode(0);//添加辅助的头节点
		pStart.next = head;
		ListNode p = head.next;
		ListNode pend = head;
		while(p!=null){
			ListNode temp = pStart.next;
			ListNode pre = pStart;
			while(temp!=p&&p.val>temp.val){
				temp = temp.next;
				pre = pre.next;
			}
			if(temp == p) pend = p;
			else{
				pend.next = p.next;
				p.next = temp;
				pre.next = p;
			}
			p = pend.next;
		}
		head = pStart.next;
		return head;
	}
	
	/**
	 * 选择排序
	 * 选择排序(算法中只是交换节点的val值,时间复杂度O(n^2),空间复杂度O(1))
	 * @param head
	 * @return
	 */
	public static ListNode selectSort(ListNode head){
		if(head == null || head.next == null) return head;
		ListNode pStart = new ListNode(0);//添加辅助的头节点
		pStart.next = head;
		ListNode tailNode = pStart;//指向已排好序的尾部节点
		
		while(tailNode.next!=null){
			ListNode minNode = tailNode.next;
			ListNode p = tailNode.next.next;
			//寻找未排序部分的最小节点
			while(p!=null){
				if(p.val<minNode.val){
					minNode = p;
				}
				p = p.next;
			}
			//交换值
			int temp = tailNode.next.val;
			tailNode.next.val = minNode.val;
			minNode.val = temp;
			
			tailNode = tailNode.next;
		}
		head = pStart.next;
		return head;
	}
	
	private static ListNode partation(ListNode head, ListNode tail) {
		int ppv = head.val;
		ListNode p = head;
		for(ListNode i = p.next;i!=tail;i = i.next){
			if(i.val<ppv){
				p = p.next;
				if(i!=p){
					swap(i,p);
				}
			}
		}
		swap(p,head);
		return p;
	}
	
	public static void quickSort(ListNode head,ListNode tail){
		if(head!=tail&&head.next!=tail){
			ListNode p = partation(head,tail);
			quickSort(head,p);
			quickSort(p.next,tail);
		}
	}

	/**
	 * 快速排序1
	 * 快速排序1(算法只交换节点的val值,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))
	 * @param head
	 * @return
	 */
	public static ListNode quickSort(ListNode head){
		if(head == null || head.next == null) return head;
		quickSort(head,null);
		return head;
	}
	
	public static ListNode partation2(ListNode preNode,ListNode head,ListNode tail){
		int ppv = head.val;
		//用两个链表分别记录比基准小的节点 和 比基准大的节点
		ListNode small = new ListNode(0);
		ListNode big = new ListNode(0);
		ListNode s = small,b = big;
		
		for(ListNode i = head.next;i!=tail;i=i.next){
			if(i.val<ppv){
				s.next = i;
				s = s.next;
			}else{
				b.next = i;
				b = b.next;
			}
		}
		//将前驱节点、小链表、基准节点、大链表、尾巴 连接起来
		b.next = tail;
		s.next = head;
		head.next = big.next;
		preNode.next = small.next;
		
		return head;
		
	}
	
	public static void quickSort2(ListNode preNode,ListNode head,ListNode tail){
		if(head!=tail && head.next!=tail ){
			ListNode p = partation2(preNode,head,tail);
			quickSort2(preNode,preNode.next,p);
			quickSort2(p,p.next,tail);
		}
	}
	
	/**
	 * 快速排序2
	 * 快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))
	 * @param node
	 * @return
	 */
	public static ListNode quickSort2(ListNode head){
		if(head == null || head.next == null) return head;
		ListNode preNode = new ListNode(0);//添加辅助的头节点
		preNode.next = head;
		quickSort2(preNode,head,null);
		return preNode.next;
	}
	
	/**
	 * 合并两个链表为有序链表
	 * @param l1
	 * @param l2
	 * @return
	 */
	private static ListNode merge(ListNode l1, ListNode l2) {
		if(l1 == null) return l2;
		if(l2 == null) return l1;
		ListNode pNode = new ListNode(0);
		ListNode p = pNode;
		while(l1!=null && l2!=null){
			if(l1.val<l2.val){
				p.next = l1;
				l1 = l1.next;
			}else{
				p.next = l2;
				l2 = l2.next;
			}
			p = p.next;
		}
		
		if(l1!=null){
			p.next = l1;
		}
		if(l2!=null){
			p.next = l2;
		}
		return pNode.next;
	}
	
	/**
	 * 归并排序
	 * 归并排序(算法交换链表节点,时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))
	 * @param head
	 */
	public static ListNode mergeSort(ListNode head){
		if(head == null || head.next == null) return head;
		//“快慢指针法”将链表分成两部分
		ListNode slow = head,fast = head;
		while(fast.next!=null && fast.next.next != null){
			fast = fast.next.next;
			slow = slow.next;
		}
		fast = slow.next;//后半部分
		slow.next = null;//断开
		//递归处理两段子链表
		ListNode l1 = mergeSort(head);
		ListNode l2 = mergeSort(fast);
		//合并两个子链表为有序链表
		return merge(l1,l2);
	}


	/**
	 * 打印链表
	 * @param head
	 */
	public static void printList(ListNode head){
		while(head!=null){
			System.out.print(head.val+" ");
			head = head.next;
		}
	}
	
	public static void main(String[] args) {
		//构建链表
		ListNode head = new ListNode(3);
		ListNode node1 = new ListNode(5);
		ListNode node2 = new ListNode(2);
		ListNode node3 = new ListNode(4);
		ListNode node4 = new ListNode(1);
		
		head.next = node1;
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		
		System.out.println("---------排序前-------");
		printList(head);
		
		//排序
//		head = mergeSort(head);
//		head = bubbleSort(head);
//		head = insertSort(head);
//		head = selectSort(head);
//		head = quickSort(head);
		head = quickSort2(head);
		
		System.out.println("---------排序后-------");
		printList(head);
	}

}

看不懂代码的话,参看下面文章的讲解:

参考文章:http://www.cnblogs.com/TenosDoIt/p/3666585.html

猜你喜欢

转载自blog.csdn.net/fxjzzyo/article/details/88205956