快速排序的三种写法

快速排序

引言

​ 孔甲己一到店,跟柜里说,“来一杯茶,要一碟茴香豆。”便排出九文大钱。看没人理自己,便对记账的小童问道,这茴香豆的茴字有四种写法,你知道么?

​ 近期闲来看了看快速排序,核心思想也就在于,找到一个可以作为中间分隔的数字,再将大的放到左边,小的放到右边,重复数次。

​ 在网上查找相关资料,找到了快速排序的3种写法

所使用到的接口和抽象类

注:只是为了练习泛型,并且让测试更加方便。

public interface Sort<T extends Comparable<? super T>> {
    void sort();

    void sort(int start, int end);
}

public abstract class BaseSort<E extends Comparable<? super E>> implements Sort<E> {
    protected E[] arr;
    
    public BaseSort(E[] arr) {
        this.arr = arr;
    }

    public E[] getArr() {
        return arr;
    }
}

基本思想

​ 选择左边第一个作为中心数pivot,我们需要将大的数放到右边,小的数放到左边。再以pivot的左右两边分别进行这个操作,就可以得到一个排序好的数组了。

三种写法

  1. 我们选择左边的第一个数作为中心数,(先把中心数保存下来,因为该位置的数待会会被替换),所以先从右边开始寻找。简单原因可以查看这篇博客.设置两个索引,一个是low,表示左边的索引,一个是high,表示右边的索引。

    此时从右往左,如果找到的数比pivot大,就一直向左找,直到找到一个比pivot小的,此时,再将左边的low指针指向的数赋值为这个数。

    再从左往右找。

    翻译为代码就是

public class MyQuickSort<E extends Comparable<? super E>> extends BaseSort<E> {
     public MyQuickSort(E[] arr) {
         super(arr);
     }
 
     @Override
     public void sort() {
         sort(0, arr.length - 1);
     }
 
     @Override
     public void sort(int start, int end) {
         if (start < end) {
             int partitionIndex = partition(start, end);
             sort(start, partitionIndex - 1);
             sort(partitionIndex + 1, end);
         }
     }
     
     private int partition(int start, int end) {
         int low = start;
         int high = end;
 
         E key = arr[low];
 
         while (inRange(low, high)) {
             while (inRange(low, high) && arr[high].compareTo(key) > 0) {
                 high--;
             }
             if (inRange(low, high))
                 arr[low++] = arr[high];
             while(inRange(low, high) && arr[low].compareTo(key) < 0) {
                 low++;
             }
             if (inRange(low, high))
                 arr[high--] = arr[low];
         }
         arr[low] = key;
 
         return low;
     }
 
     private boolean inRange(int low, int high) {
         return low < high;
     }
 
     
 }
  1. 我们还是选择第一个作为pivot,从后向前找,不过,这一次,我们从后向前找到一个比基准数小的数时,我们再从前向后找,找到比基准数大的值,将二者交换即可。

    public class MyQuickSort2<E extends Comparable<? super E>> extends BaseSort<E> {
    
        public MyQuickSort2(E[] arr) {
            super(arr);
        }
    
        @Override
        public void sort() {
            sort(0, arr.length - 1);
        }
    
        @Override
        public void sort(int start, int end) {
            if (start < end) {
                int partitionIndex = partition(start, end);
                sort(start, partitionIndex - 1);
                sort(partitionIndex + 1, end);
            }
        }
    
        private int partition(int start, int end) {
            int low = start;
            int high = end;
    
            int keyIndex = low;
            
            while (inRange(low, high)) {
                while (inRange(low, high) && arr[high].compareTo(arr[keyIndex]) > 0) {
                    high--;
                }
    
                while (inRange(low, high) && arr[low].compareTo(arr[keyIndex]) < 0) {
                    low++;
                }
    
                if (inRange(low, high)) {
                    swap(low, high--);
                }
            }
    
            swap(keyIndex, low);
    
            return low;
        }
        
        private void swap(int indexA, int indexB) {
            E temp = arr[indexA];
    
            arr[indexA] = arr[indexB];
            arr[indexB] = temp;
        }
    
        private boolean inRange(int low, int high) {
            return low < high;
        }
    }
    
  2. 这种方法来自于geeksforgeeks,这次我们选择右边的作为基准数,从左开始,使用一个临时变量指向比基准值小的数,然后循环遍历所有的数,如果当前遍历到的数比基准数小,则将其和小指针指向的下一个索引进行交换。

    public class QuickSort<E extends Comparable<? super E>> extends BaseSort<E> {
        
        public QuickSort(E[] arr) {
            super(arr);
        }
    
        @Override
        public void sort() {
            sort(0, arr.length - 1);
        }
    
        private int partition(int low, int high) {
            final E pivot = arr[high];
    
            int lowPoint = low - 1;
    
            for (int j = low; j < high; j++) {
                if (arr[j].compareTo(pivot) < 0) {
                    lowPoint++;
    
                    swap(lowPoint, j);
                }
            }
            swap(lowPoint + 1, high);
    
            return lowPoint + 1;
        }
    
        private void swap(int indexA, int indexB) {
            if (indexA == indexB) {
                return;
            }
    
            E temp = arr[indexA];
            arr[indexA] = arr[indexB];
            arr[indexB] = temp;
        }
    
        @Override
        public void sort(int start, int end) {
            if (start < end) {
                int partitionIndex = partition(start, end);
    
                // lower
                sort(start, partitionIndex - 1);
                // higher
                sort(partitionIndex + 1, end);
            }
        }
    
    }
    
发布了76 篇原创文章 · 获赞 53 · 访问量 4144

猜你喜欢

转载自blog.csdn.net/qq_42254247/article/details/105252833