排序

作者: 小婷android | 来源:发表于2018-01-22 15:25 被阅读0次

    一、选择排序

    1.堆排序

    定义:堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序
    可参考https://www.cnblogs.com/chengxiao/p/6129630
    https://www.jianshu.com/p/938789fde325

    public class HeapSort {
        public static void main(String[] args) {
    
            /**
             * 堆排序,利用二叉树左右节点的模式来比较
             */
            int[] a = {19, 8, 27, 6, 35, 14, 3, 12, 1, 0, 9, 10, 7};
    
            HeapSort heapSort = new HeapSort();
            heapSort.heapSort(a);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    
        public void heapSort(int[] a) {
            if (a == null || a.length <= 1) {
                return;
            }
    
            buildMaxHeap(a);
            for (int i = a.length - 1; i > 0; i--) {
                //最大的在0位置,那么开始沉降,这样每交换一次最大的值就丢到最后了
                exchangeElement(a, 0, i);
                //继续获取0位置最大值
                maxHeap(a, i, 0);
    
            }
    
        }
    
        /**
         * 创建最大堆
         *
         * @param a
         */
        private void buildMaxHeap(int[] a) {
            if (a == null || a.length <= 1) {
                return;
            }
            int half = (a.length ) / 2-1;
            for (int i = half; i >= 0; i--) {
                maxHeap(a, a.length, i);
            }
    
        }
    
        /**
         * 利用二叉树跟、左、右节点的值进行比较,不断的更换最大值对应的小标largest,
         * 当当前传过来的下标与最大值的小标不想等时,两者交换相应的位置,然后再用递归的方式进行查找最大,
         * 但是此时是以前面所找的最大值的小标为标准
         * @param a
         * @param length
         * @param index
         */
        private void maxHeap(int[] a, int length, int index) {
            int left = index * 2 + 1;
            int right = index * 2 + 2;
            int largest = index;
            if (left < length  && a[left] > a[index]) {
                largest = left;
            }
            if (right < length  && a[right] > a[largest]) {
                largest = right;
            }
            if (index != largest) {
                exchangeElement(a, index, largest);
    
                maxHeap(a, length, largest);
            }
        }
    
        private void exchangeElement(int[] a, int index, int largest) {
            int temp = a[index];
            a[index] = a[largest];
            a[largest] = temp;
        }
    
    }
    
    
    2,

    定义:首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。如此往复,直到将整个数组排序。这种方法叫做选择排序,因为它在不断地选择剩余元素之中的最小者。

     public static void main(String[] args) {
    
           int[] a = {3, 7, 1, 5, 6, 2, 4};
            for (int i = 0; i < a.length; i++) {
                for (int j = i + 1; j < a.length; j++) {
                    int temp;
                    if (a[i] > a[j]) {
                        temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                    }
                }
                System.out.println(a[i]);
            }
    
    
    
        }
    
    

    二、插入排序(适合小规模数组)

    1.直接插入排序

    定义:每次将一个待排序的元素与已排序的元素进行逐一比较,直到找到合适的位置按大小插入。
    自己的理解:
    在一个无序的数组中,首先将前两个元素进行对比排序,然后第三个元素和第二个元素进行对比,如果第三个元素大于第二个元素,则进行下一步,将第四个元素和第三个元素对比排序;否则如果第三个元素小于第二个元素,将两者位置互换后,再将重新排序后的第二个元素和第一个元素进行对比排序.....以此类推即可实现插入排序

    public class InsertSort {
        public static void main(String[] args) {
    
            /**
             * 直接插入排序
             */
            int[] a = {9, 3, 8, 23, 86, 33, 54, 0, 1, 65, 10, -1};
            //从数组中下标为1的元素开始
            for (int i = 1; i < a.length; i++) {
                //用temp记录当前遍历的元素值
                int temp = a[i];
                //外部定义j,为了在break的情况下记录j的值
                int j;
                for (j = i - 1; j >= 0; j--) {
                    //如果a[j]大于当前的值,则最后一个元素需要往后移动一位,所以将a[j]的值赋值给a[j+1],
                    //否则,就结束循环,记录j的值
                    if (a[j] > temp) {
                        a[j + 1] = a[j];
                    } else {
                        break;
                    }
                }
                //break下的小标为j,值比temp小,所以temp的值需要赋值给a[j+1]
                a[j + 1] = temp;
            }
    
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    }
    
    
    2.二分法插入排序

    先要知道数组中的左边、右边以及中间的下标,然后当坐标下标小于等于右边下标时,将要插入的数字与中间下标对应的数字进行比较,做变换左、中、右下标的循环,最后以左下标为标准,将左及左后边全部后移,当左下标的值不等于i时,左位置插入该数据。

    public class BinaryInsertSort {
        public static void main(String[] args) {
            int[] a = {3, 0, 1, 90, 56, 34, 23, 76, 46, -1, 77};
            BinaryInsertSort b = new BinaryInsertSort();
            b.sort(a);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    
        /**
         * 二分法插入排序
         *
         * @param a
         */
        public void sort(int[] a) {
            for (int i = 1; i < a.length; i++) {
                //记录当前遍历到的数值
                int temp = a[i];
                //定义左边的下标
                int left = 0;
                //定义右边的下标
                int right = i - 1;
                //初始化中间的下标
                int mid = 0;
                //循环:当左边下标小于等于右边下标时
                while (left <= right) {
                    //计算中间下标
                    mid = (left + right) / 2;
                    //当当前遍历的值�大于中间小标对应的值时,变动左边下标
                    if (temp > a[mid]) {
                        left = mid + 1;
                    } else {
                        //当当前遍历的值小于中间小标对应的值时,变动右边下标
                        right = mid - 1;
                    }
                }
    
                //遍历数组,以左下标为标准,让大于等于左边下标对应的所有的值都往后移动一位
                for (int j = i - 1; j >= left; j--) {
                    if (temp < a[j]) {
                        a[j + 1] = a[j];
                    }
    
                }
    
                //当左边下标不等于遍历的小标时(即要插入的那个数在当前排序数字中不是最大时),给左边下标对应的数赋值
                //要插入的那个数在当前排序数字中是最大时,直接插入,不做任何操作
                if (left != i) {
                    a[left] = temp;
                }
            }
    
    
        }
    }
    
    
    3.希尔排序

    定义:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止


    希尔排序过程
    public class HeerSort {
        public static void main(String[] args) {
            /**
             * 希尔排序
             */
            int[] a = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 1, 33, 85, 29};
            int d = a.length / 2;   //默认增量,总长度除以2
            while (true) {
                for (int i = 0; i < d; i++) {//注意i的值是小于增量的
                    for (int j = i; j + d < a.length; j += d) {//以增加作为间距
                        int temp;
                        if (a[j] > a[j + d]) {
                            temp = a[j];
                            a[j] = a[j + d];
                            a[j + d] = temp;
                        }
                    }
                }
                //增量为1时结束
                if (d == 1) {
                    break;
                }
                d--;
            }
    
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    }
    
    

    三、快速排序

    定义:是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

    public class QuickSort {
        public static void main(String[] args) {
            QuickSort quickSort = new QuickSort();
            int[] a = {19, 2, 6, 90, 67, 33, -7, 24, 3, 56, 34, 5};
            quickSort.quick(a);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    
        public void quick(int[] a) {
            if (a.length < 0) {
                return;
            }
            quickSort(a, 0, a.length - 1);
    
        }
    
        /**
         * 快速排序
         *
         * @param a
         * @param low
         * @param high
         */
        private void quickSort(int[] a, int low, int high) {
            //获取下标后,以该下标为基准,用迭代的方法左右两边都做相同的操作
             if (low < high) {
                int middle = getMiddle(a, low, high);
                quickSort(a, 0, middle - 1);
                quickSort(a, middle + 1, high);
            }
        }
    
        /**
         * 以数组中的一个数为基准元素,然后获取该元素在此数组中的排序的下标
         * @param a
         * @param low
         * @param high
         * @return
         */
        private int getMiddle(int[] a, int low, int high) {
            int temp = a[low];//以下标为low的值作为基准元素
            while (low < high) {
                //从右边开始,一个个与基准元素进行比较,大于基准元素的,high--,小于基准元素的,结束循环
                while (low < high && temp < a[high]) {
                    high--;
                }
                //结束循环之后,将a[high]的值放到a[low]中,
                a[low] = a[high];
    
                //在从左边开始,一个个与基准元素进行比较,小于基准元素的,low++;大于基准元素的,结束循环
                while (low < high && temp > a[low]) {
                    low++;
                }
                //结束循环之后,将a[low]的值放到a[high]中,
                a[high] = a[low];
            }
            a[low] = temp;
            return low;
        }
    }
    
    

    四、归并排序

    定义:是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表;
    基本思想:分而治之(divide - conquer);每个递归过程涉及三个步骤
    第一, 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
    第二, 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
    第三, 合并: 合并两个排好序的子序列,生成排序结果.

    image
    public class MergeSort {
        public static void main(String[] args) {
            int[] a = new int[]{90, 3, 2, 67, 44, -9, 87, 65, 11, 9, 2, 8};
            MergeSort m = new MergeSort();
            m.mergeSort(a, 0, a.length - 1);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    
        /**
         * 归并排序
         * @param a
         * @param left
         * @param right
         */
        public void mergeSort(int[] a, int left, int right) {
            if (left < right) {
                int middle = (left + right) / 2;
                //将数组拆分成单个元素的多个数组
                mergeSort(a, left, middle);
                mergeSort(a, middle + 1, right);
                //逐一合并
                merge(a, left, middle, right);
            }
    
        }
    
        /**
         * 合并排好序的数组,定义一个新的数组,然后两个数组从第一个开始进行比较,
         * 谁小就放入新的数组,同时对应的下标加或者减1,
         * @param a
         * @param left
         * @param middle
         * @param right
         */
        private void merge(int[] a, int left, int middle, int right) {
            int[] tempArray = new int[a.length];
            int rightStart = middle + 1;
            int temp = left;
            int third = left;
            //当左边小于等于中间;右边开始下标小于等于右边
            while (left <= middle && rightStart <= right) {
                //从第一个元素开始逐个比较,如果左边的值小于右边的值,将左边的值放在新的数组中,否则,将右边的值放在新的数组中
                if (a[left] <= a[rightStart]) {
                    tempArray[third++] = a[left++];
    //                tempArray[third]=a[left];
    //                third++;
    //                left++;
                } else {
                    tempArray[third++] = a[rightStart++];
                }
            }
    
            //当右边的数组全部比较完了,但是左边的依然还有,则将左边剩余的元素依次放入新的数组中
            while (left <= middle) {
                tempArray[third++] = a[left++];
            }
            //当左边的数组全部比较完了,但是右边的依然还有,则将右边剩余的元素依次放入新的数组中
            while (rightStart <= right) {
                tempArray[third++] = a[rightStart++];
            }
    
            while (temp <= right) {
                a[temp] = tempArray[temp];
                temp++;
            }
    
    
        }
    }
    
    

    五、基数排序

    基本思路:

    • 第一:获取数组中的最大值以及最大值的位数;
    • 第二:创建一个多维数组,里面有十个数组,分别存放位数对应的1-10的数字;
    • 第三:遍历原始数组,分别获取个位、十位、百位等位对应的值,通过这个值获取在多维数组中对应的数组,
    • 把原始数组中的这个元素添加到多维数组中对应的数组中,
    • 第四:开始收集;遍历多维数组中的每个数组,把每个数组中的元素一个个赋值给原始数组元素,赋值一个,移除一个,同时count次数++
    public class BasicSort {
        public static void main(String[] args) {
            int[] a = {136, 2, 6, 8, 9, 2, 8, 11, 23, 56, 34, 90, 89, 29, 145, 209, 320, 78, 3};
            BasicSort basicSort = new BasicSort();
            basicSort.sort(a);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
        }
    
        /**
         * 基数排序:
         * 基本思路:
         * 第一:获取数组中的最大值以及最大值的位数;
         * 第二:创建一个多维数组,里面有十个数组,分别存放位数对应的1-10的数字;
         * 第三:遍历原始数组,分别获取个位、十位、百位等位对应的值,通过这个值获取在多维数组中对应的数组,
         * 把原始数组中的这个元素添加到多维数组中对应的数组中,
         * 第四:开始收集;遍历多维数组中的每个数组,把每个数组中的元素一个个赋值给原始数组元素,赋值一个,移除一个,
         * 同时count次数++
         *
         * @param a
         */
        public void sort(int[] a) {
            //获取数组中的最大值
            int max = 0;
            for (int i = 0; i < a.length; i++) {
                if (max < a[i]) {
                    max = a[i];
                }
            }
    
            //获取最大值的位数
            int times = 0;
            while (max > 0) {
                max = max / 10;
                times++;
            }
    
            //创建一个多维数组
            List<ArrayList> queue = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                ArrayList q = new ArrayList();
                queue.add(q);
            }
    
            for (int i = 0; i < times; i++) {
                for (int j = 0; j < a.length; j++) {
                    //获取对应的位的值(i为0是各位,1是10位,2是百位)
                    int x = a[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                    //通过得到的位的值获取多维数组中对应的数组,然后将该数据添加到对应的数组中
                    ArrayList q = queue.get(x);
                    q.add(a[j]);
                }
    
                //开始收集
                int count = 0;
                //遍历多维数组中的每个数组
                for (int j = 0; j < 10; j++) {
                    while (queue.get(j).size() > 0) {
                        ArrayList<Integer> q = queue.get(j);//获取多维数组中的单个数组
                        //将第一个值赋值给原有的数组,然后移除第一个
                        a[count] = q.get(0);
                        q.remove(0);
                        count++;
    
                    }
                }
            }
    
        }
    }
    
    

    六、二分查找

    public class BinarySearch {
        public static void main(String[] args) {
            int[] array = {10, 23, 4, 3, 2, 5, 1, 2, 623, 92, 23, 23, 234, 2, 34, 234, 234, 2, 10};
            BinarySearch binarySearch = new BinarySearch();
            BasicSort basicSort = new BasicSort();
            basicSort.sort(array);
            for (int i = 0; i < array.length; i++) {
                System.out.print(array[i] + "---");
            }
    //        binarySearch.binarySearch(5, array, 0, array.length - 1);
            binarySearch.directBinarySearch(array,5);
    
    
        }
    
        /**
         * 递归查找(二分查找)
         *
         * @param elem
         * @param array
         * @param low
         * @param high
         * @return
         */
        public int binarySearch(int elem, int[] array, int low, int high) {
            if (low > high) {
                return -1;
            }
            int middle = (low + high) / 2;
            if (elem < array[middle]) {
                //找左边
                return binarySearch(elem, array, low, middle - 1);
            } else if (elem > array[middle]) {
                //找右边
                return binarySearch(elem, array, middle + 1, high);
            } else if (elem == array[middle]) {
                System.out.print("-------" + middle);
                return middle;
            } else {
                return -1;
            }
    
        }
    
        /**
         * 非递归查找
         * @param array
         * @param elem
         * @return
         */
        public int directBinarySearch(int[] array, int elem) {
            int low = 0;
            int high = array.length - 1;
            while (low <= high) {
                int middle = (low + high) / 2;
                if (elem < array[middle]) {
                    high = middle - 1;
                } else if (elem > array[middle]) {
                    low = middle + 1;
                } else if (elem == array[middle]) {
                    System.out.print("-------" + middle);
                    return middle;
                }
            }
            return -1;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:排序

          本文链接:https://www.haomeiwen.com/subject/nnelaxtx.html