单链表快排与数组快排
时间:2020.07.23
一、传统快排思想
思想简介:
-
传统的快速排序算法使用到递归
-
快排是对冒泡排序算法的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按照此方法对两部分数据使用
递归
进行如上操作。使得整个数据达到有序序列。
特点:在单项链表中无法应用。
图解
流程
Java代码
package demo08;
import java.text.BreakIterator;
import java.util.Arrays;
/**
* @author jiyongjia
* @create 2020/7/23 - 10:27
* @descp:
*/
public class Demo01_kuaipai {
public static void main(String[] args) {
int[] arr = new int[]{-9,78,0,23,-2,70,-32,323,-222,421};
quickSort1(arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr,int left,int right){
int l = left;
int r = right;
int mid = (l+r)/2;
int midValue = arr[mid];
while (l<r){
//左找
while(arr[l]<midValue){
l++;
}
//右找
while(arr[r]>midValue){
r--;
}
//判断退出条件
if(l>=r){
break;
}
//不然的话就交换
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//处理边界条件
if(arr[l] == midValue){
r--;
}
if(arr[r] == midValue){
l++;
}
}
//处理死锁
if(l==r){
l++;
r--;
}
//左递归
if(left<r){
quickSort(arr,left,r);
}
//右递归
if(right>l){
quickSort(arr,l,right);
}
}
public static void quickSort1(int[] arr,int left,int right){
int l = left;
int r = right;
int mid = (l+r)/2;
int midValue = arr[mid];
while (l<r){
//左边找
while(arr[l]<midValue){
l++;
}
//右边找
while (arr[r]>midValue){
r--;
}
//判断退出条件
if (l>=r){
break;
}
//找到交换的两个数字就交换
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//防止死锁
if(arr[l]==midValue){
r--;
}
if(arr[r]==midValue){
l++;
}
}
if(l==r){
l++;
r--;
}
//左递归
if(r>left){
quickSort1(arr,left,r);
}
if(l<right){
quickSort1(arr,l,right);
}
}
}
二、快排新思想
思想:
案例
特点:
可以应用在数组,也可以应用在单向链表
实现对数组的快排
Java代码:
package demo08;
import java.util.Arrays;
/**
* @author jiyongjia
* @create 2020/7/23 - 16:33
* @descp: 快排数组
*/
public class Demo06_quickSort2 {
public static void main(String[] args) {
int[] ints = {-2, 3, 5, 3, 88, 8, 1};
quickSort(ints,0,ints.length-1);
System.out.println(Arrays.toString(ints));
}
public static void quickSort(int[] arr, int left, int right) {
//递归的结束条件
if(left<right){
int base = arr[left]; //选择一个基本的比较的节点,每次默认是该组元素的第一个
int i = left+1; // i和j指针都是指向了base后的那个元素
int j = left+1;
//j指针一直在后移比较,如果发现小于base的数就和base交换,并且i++;j++;
//如果j的值不大于base,就j指针一直后移,直到结束
while (j<=right){
if(arr[j]<base){
swep(arr,i,j);
i++;
}
j++;
}
//当j走到头的时候,那么此时就找新的base的位置(老base位置和i指针前的那个数交换)
swep(arr,left,i-1);
//左递归
quickSort(arr,left,i-2);
//右递归
quickSort(arr,i,right);
}
}
//负责交换的函数
public static void swep(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
输出:
实现对链表的快排
Java代码:
package demo08;
import com.sun.jndi.toolkit.ctx.StringHeadTail;
/**
* @author jiyongjia
* @create 2020/7/23 - 20:37
* @descp: 快排单链表
*/
public class Demo07_quickSortLinkedList {
//测试用例
public static void main(String[] args) {
Node head = new Node(2);
Node node1 = new Node(1);
Node node2 = new Node(65);
Node node3 = new Node(3);
Node node4 = new Node(8);
head.next=node1;
node1.next=node2;
node2.next=node3;
node3.next=node4;
//排序前的链表
System.out.println("排序前的链表情况:");
Node dummy = head;
while (dummy!=null){
System.out.print(dummy+"==>>");
dummy = dummy.next;
}
//调用
entrance(head);
}
//主要入口方法
public static void entrance(Node head){
//如果题目只给了头节点,我们需要遍历出尾节点
Node cur = head;
while (cur.next!=null){
cur = cur.next;
}
//调用链表快排
quickSortLinkedList(head,cur);
//打印出最终的链表情况
System.out.println("
排序后的链表情况:");
while (head!=null){
System.out.print(head+"==>>");
head = head.next;
}
}
//链表快排算法
public static void quickSortLinkedList(Node head,Node tail){
if(head==null || head.next==null || head==tail) {
return;//结束
}
Node base = head; //基准比较的值,默认是本组的头节点
Node i = head.next; //i指针是头节点后
Node i_pre = head; //记录i的前一个节点
Node j = head.next; //j指针是头节点后
while (j!=tail.next){ //j走完了整个链表,走到tail
if(j.val < base.val){
swep(i,j); //执行交换i 和 j的值
i_pre = i; //先记录i的前一个值
i = i.next;//再让i指针后移
}
j = j.next; //j指针后移
}
//退出while即走到链表尾部,重新找base节
swep(head,i_pre);
//左递归
quickSortLinkedList(head,i_pre);
//右递归
quickSortLinkedList(i,tail);
}
//交换两节点中的值
private static void swep(Node i,Node j) {
int temp = i.val;
i.val = j.val;
j.val = temp;
}
}
//节点定义
class Node{
int val;
Node next;
public Node(int val){
this.val = val;
}
@Override
public String toString() {
return "Node{" +
"val=" + val +
'}';
}
}
输出测试结果: