[编程题] 单链表快排与数组快排

单链表快排与数组快排

时间:2020.07.23

一、传统快排思想

思想简介:

  • 传统的快速排序算法使用到递归

  • 快排是对冒泡排序算法的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按照此方法对两部分数据使用递归进行如上操作。使得整个数据达到有序序列。

特点:在单项链表中无法应用。

图解

image-20200723104736343

流程

image-20200723105722241

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);
        }
    }
}

二、快排新思想

思想:

image-20200723202940258

案例

image-20200723203011733

特点:

​ 可以应用在数组,也可以应用在单向链表

实现对数组的快排

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;
    }

}

输出:

image-20200723213918044

实现对链表的快排

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("\n排序后的链表情况:");
        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 +
                '}';
    }
}

输出测试结果:

image-20200723213614099

猜你喜欢

转载自www.cnblogs.com/jiyongjia/p/13368944.html