• 排序算法


    冒泡排序

    冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来,假设从小到大,即为较大的数慢慢往后排,较小的数慢慢往前排。

    直观表达,每一趟遍历,将一个最大的数移到序列末尾。

    void bubbleSort(int* array, int len) {
        for (int n = 0; n < len - 1; n++) {
            for (int m = 0; m < len - 1 - n; m++) {
                if (array[m] > array[m + 1]) {
                    int tmp = array[m];
                    array[m] = array[m + 1];
                    array[m + 1] = tmp;
                }
            }
        }
    }

    选择排序

    每一次遍历待排序的序列,记录最小值的下标,和待排序第一个元素进行比较,如果小与待排序第一个元素,交换

    void selectSort(vector<int>& arr) {
        for (int i = 0, k = 0; i < arr.size(); i++, k = i){
            // 这一层查找后面最小值的下标
            for (int j = i + 1; j < arr.size(); j++) {
                if (arr[k] > arr[j]) {
                    k = j;
                }
            }
            // 交换值
            if (i != k) {
                int temp = arr[i];
                arr[i] = arr[k];
                arr[k] = temp;
            }
        }
    }

    插入排序

    插入的意思是指将一个元素插入一个已排序序列中,选择好插入位置后,需要将插入位置以后的元素依次往后移动一个位置。

    void InsertionSort(int *array, int N)
    {
          int j, k, key;
          for (j=1; j<N; j++) {
                key = array[j];
                for (k=j-1; k>=0 && key<array[k]; k--) {
                       array[k+1] = array[k]; 
                 } 
                 array[k+1] = key;
          } 
    }

    快速排序

    在待排序序列中选择一个支点,以该支点为界,序列中比它小的元素放到它前面,比它大的元素放到它后面。

    int partition(int *array, int p, int r)
    {
        int key = array[r];
        int i = p; 
        int j;
        for (j=p; j<r; j++) {
            if (array[j] <= key)
                swap(&array[i++], &array[j]);
        }  
        swap(&array[i], &array[r]);
        return i;
    }
    
    void QSort(int *array, int p, int r)
    {
        int q;
        if (p < r) {
            q = partition(array, p, r);
            QSort(array, p, q-1);
            QSort(array, q+1, r);
        }  
    }

    归并排序

    采用分治算法, 

    void merge(int* array, int p, int mid, int r) {
        vector<int> aux(r - p + 1);
        for (int k = p; k <= r; k++) {
            aux[k] = array[k];
        }
    
        int i = p;          // left: [p, mid]
        int j = mid + 1;    // right: [mid + 1, r]
        for (int k = p; k <= r; k++) {
            if (i > mid) array[k] = aux[j++];
            else if (j > r) array[k] = aux[i++];
            else if (aux[j] < aux[i]) array[k] = aux[j++];
            else array[k] = aux[i++];
        }
    }
    
    void mergeSort(int* array, int p, int r) {
        if (p >= r) return;
        int mid = (p + r) / 2;
    
        mergeSort(array, p, mid);
        mergeSort(array, mid + 1, r);
        merge(array, p, mid, r);
    }

    堆排序

    参考这里

    计数排序

    假设输入数组A[1,...,n]中的每一个元素都满足 0<=A[i]<=k,可以借助一个辅助的k维数组C[0,...,k]来对数组A排序,并将排序后的结果输出到数组B;
     
    实现步骤:
    1、找出待排序数组A中的最大和最小的元素;
    2、统计数组A中每个值为i的元素出现的次数,存入数组C的第i项;
    3、对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
    4、反向填充目标数组B,将每个元素i放在B[C[i]],每放一个元素就将C[i]减1;

    void CountingSort(int *A, int *B, int N) {
         int n = 0;
         const int K = 1 + max(A, N);
         int C[K];
         for (n=0; n<K; n++)
              C[n] = 0;
        
         for (n=0; n<N; n++)
              C[A[n]]++;
    
         for (n=1; n<K; n++)
              C[n] += C[n-1];
    
         for (n=N-1; n>=0; n--) {
              B[C[A[n]] - 1] = A[n];
              C[A[n]]--;
         }
    
    }

    桶排序

    桶排序是将数组分到有限数量的桶子里,每个桶里面再分别排序。
    当待排序数组内的数值服从均匀分布的时候,桶排序使用线性时间O(n)。
     
     
     
     

    基数排序

    思路:
    1、将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零;
    2、从低位开始,依次进行一次排序,这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
     
     
     
     
     

    希尔排序

    topK

    问题描述:在数组A[p,...,r]中找到第k小的元素key,显然0<=k<=(r-p+1);
     
    思路:可以借鉴快速排序的分治算法,如下
    1、将A[p,...,r]划分成两个子数组A[p,...,q-1]和A[q+1,...,r];
    2、然后判断第k小的元素key位于哪个子数组中;
    3、如果k==(q-p+1),则返回key=A[q];
    4、如果key位于第一个子数组,则继续在A[p,...,q-1]中求第k小的元素;
    5、如果key位于第二个子数组,则在A[q+1,...,r]中求第(k-(q-p+1))小的元素;

    int partition(int *array, int p, int r) {
        int key = array[r];
        int i, j = p;
        for (i = p; i < r; i++) {
            if (array[i] <= key) {
                swap(&array[j++], &array[i]);
            }
        }
        swap(&array[j], &array[r]);
        return j;
    }
    
    int topk(int *array, int p, int r, int k) {
        if (p == r) return array[p];
    
        int q = partition(array, p, r);
    
        if (p + k - 1 == q) {
            return array[q];
        } else if (p + k - 1 > q) {
            return topk(array, q + 1, r, k - (q - p + 1));
        } else {
            return topk(array, p, q - 1, k);
        }
    }
  • 相关阅读:
    GCC学习笔记2
    $gcc help
    JVM证书制作步骤+耶鲁 CAS 配置
    oracle VARRAY与for .. loop
    docx转doc的方法
    java keytool 安全证书学习
    数字的格式化(简单几个,不过觉得很有用)
    人应该怎样的活着?!
    转;关于ORM
    终于可以回家了!
  • 原文地址:https://www.cnblogs.com/chenny7/p/14156182.html
Copyright © 2020-2023  润新知