• 排序算法


    1)插入排序(稳定)。从第二个元素开始,依次从剩余元素中选择一个,插入到前面有序的子序列中。在元素数量较少时,比较高效。

    public static void insertSort(int[] nums){
            if ( nums == null ){
                return;
            }
            int len = nums.length;
            int tmp, j;
            for(int i = 1; i < len; ++i){
                tmp = nums[i];
                j = i - 1;
                while( j >= 0 && tmp < nums[j]){
                    nums[j + 1] = nums[j];
                    j--;
                }
                nums[j + 1] = tmp;
            }
        }

    2)快速排序(不稳定,平均时间复杂度O(nlogn))

    public void quickSort(int[] a, int low, int high) {
            if (low < high) {
                int location = partition(a,low,high);
                quickSort(a, low, location - 1);
                quickSort(a, location + 1, high);
            }
        }
        
        public int partition(int[] a, int left, int right) {
            if (left < right) {
                int pivot = a[left];
                while(left < right){
                    while (left < right && a[right] >= pivot) {
                        right--;
                    }
                    a[left] = a[right];
                    while (left < right && a[left] <= pivot) {
                        left++;
                    }
                    a[right] = a[left];
                }
                a[left] = pivot;
            }
            return left;
        }

    3)归并排序(稳定,时间复杂度O(nlogn))

    public void mergeSort(int[] a, int low, int high) {
            if (low < high) {
                int mid = (low + high) / 2;
                mergeSort(a, low, mid);
                mergeSort(a, mid + 1, high);
                merge(a, low, mid, high);
            }
        }
        
        public void merge(int[] a, int left, int mid, int right) {
            if (left < right){
                int len = right - left + 1;
                int[] b = new int[len];
                int i = left, j = mid + 1, k = 0;
                while(i <= mid && j <= right){
                    if (a[i] <= a[j]) {
                        b[k++] = a[i++];
                    } else {
                        b[k++] = a[j++];
                    }
                }
                while (i <= mid) {
                    b[k++] = a[i++];
                }
                while (j <= right) {
                    b[k++] = a[j++];
                }
                for (int l = 0; l < k; ++l){
                    a[l + left] = b[l];
                }
            }
        }

    4)堆排序(不稳定,时间复杂度O(nlogn))

        /**
         * 堆排序
         * @param a
         */
        public void heapSort(int[] a) {
            if (a == null || a.length == 0) {
                return;
            }
            int len = a.length;
            for (int i = 0; i < len; ++i){
                //createMaxHeap(a,len - 1 - i); //从小到大排序
                createMinHeap(a, len - 1 - i); // 从大到小排序
                swap(a, 0, len - 1 - i);
            }
        }
        
        // 建堆以及调整堆
        public void createMaxHeap(int[] a, int lastIndex) {
            for(int j = (lastIndex - 1) / 2; j >= 0; --j){ // 从最后一个非叶子结点开始调整
                int k = j;
                
                // 调整以k结点为根的子树
                while(2 * k + 1 <= lastIndex){
                    // 找到孩子结点中的值较大者
                    int biggerIndex = 2 * k + 1; // 至少有一个左孩子
                    if (biggerIndex < lastIndex) { // 存在右孩子
                        if (a[biggerIndex] < a[biggerIndex + 1]) {
                            biggerIndex++;
                        }
                    }
                    
                    if (a[k] < a[biggerIndex]) { // 需要调整子树
                        swap(a, k, biggerIndex);
                        k = biggerIndex; // 循环调整
                    } else { // 不需要调整该子树,break。继续从下一个非叶子结点开始调整
                        break;
                    }
                }
            }
        }
        
        // 建堆以及调整堆
        public void createMinHeap(int[] a, int lastIndex) {
            for(int j = (lastIndex - 1) / 2; j >= 0; --j){ // 从最后一个非叶子结点开始调整
                int k = j;
                
                // 调整以k结点为根的子树
                while(2 * k + 1 <= lastIndex){
                    // 找到孩子结点中的值较小值
                    int lessIndex = 2 * k + 1; // 至少有一个左孩子
                    if (lessIndex < lastIndex) { // 存在右孩子
                        if (a[lessIndex + 1] < a[lessIndex]) {
                            lessIndex++;
                        }
                    }
                    
                    if (a[k] > a[lessIndex]) { // 需要调整子树
                        swap(a, k, lessIndex);
                        k = lessIndex; // 循环调整
                    } else { // 不需要调整该子树,break。继续从下一个非叶子结点开始调整
                        break;
                    }
                }
            }
        }    
        
        public void swap(int[] a, int i, int j) {
            int tmp = a[i];
            a[i] = a[j];
            a[j] = tmp;
        }

    5)计数排序、基数排序、桶排序。

        上述1-4是最常见和最常用的几种排序算法。但是,在大数据量排序时,依然具有较大的时间和空间复杂度。因此,需要寻求新的排序方式。

        a)若了解排序对象的已知限制情况,可以使用计数排序。比如对成绩、年龄、日期等具有上下限的数据。

        b)若对大数据量求前100名、前10名、排行榜等,可以采用降维的方法,对数据进行一次扫描即可得到所求结果。

              比如求前10大,可以用10个空间,放入前10个,从大到小排好序。依次遍历剩余的数据,若其比最小者大,则交换两者,对新的10个元素重新排序;若其比较小者还小,则指针继续向下遍历。

        c)桶排序:将大数据划分为n个桶,对各个桶中的数据进行排序,然后再将各个桶中的有序数据汇总排序,得到最终的有序序列。

              比如:对考生试卷得分排序。低于60分的一个桶,60-80一个桶,80-100一个桶。

    6)Tim sort?

    7)判断一个链表是否是双向循环链表?

  • 相关阅读:
    浮动广告
    jQuery给table添加行和删除行
    oracle优化方式和sql标准
    使用JavaScript中的ActiveXObject填充并设置Excel格
    打印相关的js
    利用js导出Excel
    Oracle左外连接和右外连接的写法
    天气预报抓取的方法和源代码(包括从IP获取)
    algorithm
    ungetc
  • 原文地址:https://www.cnblogs.com/mydesky2012/p/8075613.html
Copyright © 2020-2023  润新知