zoukankan      html  css  js  c++  java
  • [编程题] 单链表快排与数组快排

    单链表快排与数组快排

    时间: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("
    排序后的链表情况:");
            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

  • 相关阅读:
    在eclipse创建android project,最后一步点击finish没反应
    有哪些可以将网页另存图片的chrome插件?功能类似网页截图
    极品家丁—优酷全网独播喜剧
    如何安装chrome扩展?比如json-handle插件如何安装
    安装用户脚本的福音:Tampermonkey(油猴)
    多微博账号同时发微博的插件--fawave
    正能量-真正男子汉2
    如何看待优酷广告?
    秋雨连绵思晚天
    如何用Postman组装Request并且查看Response
  • 原文地址:https://www.cnblogs.com/jiyongjia/p/13368944.html
Copyright © 2011-2022 走看看