算法系列--排序算法(四)快速排序

快速排序是通过两个指针相互交换完成一次快速排序,类似于递归的二分排序,从交换上来讲比较像冒泡(为什么这么说呢?不管是插入还是直接,都需要在移动之前遍历元素;冒泡直接比较交换。)

上面的可能有点抽象,我是不太想抄一个百度定义去解释,可能对算法理解上不太好。

通过两个指针:一个标记用来比较二分的对象,一个标记标记下一个要进行二分标记的数字;一次快速排序中包含多个二分过程。

图解(升序):

数据 4 2 5 1 3 7 6
下标 0 1 2 3 4 5 6

1)指针1:【0】- 4 ; 指针2:【6】- 6 ;指针1是用来二分的标准,指针2是被二分的元素,过程如下;
 

数据 4 2 5 1 3 7 6
下标 0 1 2 3 4 5 6

    当指针2走到数组下标是4的时候判断当前数据不符合排列顺序,交换两个指针的数据;然后指针1开始作为移动指针向右移动;

数据 3 2 5 1 4 7 6
下标 0 1 2 3 4 5 6

2)指针1:【0】- 3 ; 指针2:【4】- 4 ;两个指针在这个过程中是一个相互靠近的过程,不断交换不符合顺序的数据;

数据 3 2 5 1 4 7 6
下标 0 1 2 3 4 5 6

     当指针1走到下标2时判断当前数据不符合排列顺序,交换两个指针的数据;然后指针2开始作为移动指针向左移动;

数据 3 2 4 1 5 7 6
下标 0 1 2 3 4 5 6

3)指针1:【2】- 4 ; 指针2:【4】- 5 ;当两个指针相等的时候,结束当前的二分过程;

数据 3 2 1 4 5 7 6
下标 0 1 2 3 4 5 6

以上为一个二分过程,然后形成的两个区域的值,同样重复二分操作,直到区间长度为1;

时间复杂度:在二分查找的基础上每层都会有一次当前范围的遍历所以时间复杂度 n*logn (logn 是以2为底n的对数) 

代码实现:

/**
 * FastSort 升序
 *
 * @Date 2018/8/19
 * @Author joker
 **/
public class FastSortTest {

    private int[] data;

    {
        data = initData(100, 200);
    }

    /**
     * DFS 深度遍历(递归)
     */
    @Test
    public void recursiveTest() {
        recursive(data, 0, 99);
        System.out.println("排序结果:");
        System.out.println(new Gson().toJson(data));
    }

    /**
     * BFS 广度遍历(非递归)
     */

    @Test
    public void nonRecursiveTest() {
        class Node {
            private int start;
            private int end;

            public Node(int start, int end) {
                this.start = start;
                this.end = end;
            }
        }
        LinkedList list = new LinkedList<>();
        list.add(new Node(0, data.length - 1));
        while (!list.isEmpty()) {
            Node node = list.poll();
            int start = node.start, end = node.end;
            boolean flag = true;
            while (node.start < node.end) {
                if (data[node.start] > data[node.end]) {
                    int tmp = data[node.end];
                    data[node.end] = data[node.start];
                    data[node.start] = tmp;
                    if (flag) {
                        node.start++;
                    } else {
                        node.end--;
                    }
                    flag ^= true;
                    continue;
                }
                if (!flag) {
                    node.start++;
                } else {
                    node.end--;
                }
            }
            if (start < node.start - 1) {
                list.add(new Node(start, node.start - 1));
            }
            if (end > node.end + 1) {
                list.add(new Node(node.end + 1, end));
            }
        }
        System.out.println("排序结果:");
        System.out.println(new Gson().toJson(data));

    }

    private void recursive(int[] data, int start, int end) {
        int range_s = start, range_e = end;
        boolean flag = true;
        while (start < end) {
            if (data[start] > data[end]) {
                int tmp = data[end];
                data[end] = data[start];
                data[start] = tmp;
                if (flag) {
                    start++;
                } else {
                    end--;
                }
                flag ^= true;
                continue;
            }
            if (!flag) {
                start++;
            } else {
                end--;
            }
        }
        if (range_s < start - 1) {
            recursive(data, range_s, start - 1);
        }
        if (range_e > end + 1) {
            recursive(data, end + 1, range_e);
        }
    }

    private int[] initData(int length, int maxRange) {
        int[] data = new int[length];
        IntStream.range(0, length).forEach(e -> {
            data[e] = new Double(Math.random() * maxRange).intValue();
        });
        System.out.println("初始化:");
        System.out.println(new Gson().toJson(data));
        return data;
    }
}

 

你可能感兴趣的:(算法)