数据结构中几种排序算法的整理

来源:互联网 发布:python help 函数 编辑:程序博客网 时间:2024/06/07 00:34

几种排序算法的整理

  • 选择排序
  • 交换排序
  • 插入排序
  • 归并排序
  • 各种排序算法的比较

    1. 选择排序

    主要思想: 给定一个序列,从中选出一个最值作为第一个元素,之后重复这一步骤,直到所有元素都被放置在确定的位置,主要的算法有简单选择排序和堆排序。

    • 简单选择排序
      该算法的平均时间复杂度是O(n^2),空间复杂度为O(1),属于不稳定排序。每趟排序都能定下一个元素的位置。以下为算法的实现代码:
  public static void SelectSort(int[] array, int n) {        int min, k;        for (int i = 0; i < n; i++) {            min = i;//min用于标记最小元素的下标位置            for (int j = i; j < n; j++) {                if (array[j] < array[min]) {                    min = j;                }            }            if (i != min) {                k = array[i];                array[i] = array[min];                array[min] = k;            }        }    }  

即给定一个数组,从下标i=0开始判断,每次找寻出最小的元素,与i位置的元素交换,使得每次的最小值放置到i处,i++,重复以上操作,直到i=n-1,结束排序。

  • 堆排序
    该算法的平均时间复杂度是O(nlogn),空间复杂度为O(1),属于不稳定排序算法。每趟排序都能定下一个元素的位置。以下为算法的实现代码:
public static void HeapSort(int[] arrayt, int n) {    int[] array = new int[n + 1];    for (int i = 1; i <= n; i++)      array[i] = arrayt[i - 1];// 数组从下标1开始存数据,便于树的遍历    int k;    for (int i = n / 2; i > 0; i--)    // 初始化调整堆,从n/2(最后一个非叶子结点)处向上调整堆        HeapAdjust(array, i, n);    for (int i = n; i > 1; i--) {    // 每次调整,都能确定一个元素的位置 放在i位置        k = array[i];        array[i] = array[1];        array[1] = k;// 将堆顶元素与未排序序列的最后一个元素互换        HeapAdjust(array, 1, i - 1);// 调整堆    }    for (int j = 1; j < n; j++)        System.out.print(array[j] + " ");    System.out.println(array[n]);}    /** 向下调整堆的算法    *  array  待排序数组       *  s      堆调整的起始下标        *  m      堆调整的终止下标    */public static void HeapAdjust(int[] array, int s, int m) {    int k = array[s];    for (int i = 2 * s; i <= m; i = i * 2) {        if (i < m && array[i] < array[i + 1])// 求出左右子树中比较小的结点           i++;        if (k >= array[i]) // 使得父节点为最大值结点                break;        array[s] = array[i];        s = i;     }    array[s] = k;}

即,将数组元素搭建成树形结构,首先建立初始堆(大顶堆),然后将堆顶元素和未排序序列的最后一个元素互换。之后不断调整堆,并交换堆顶元素和未排序序列的最后一个元素。重复上述操作,直到所有元素排序完成。

2. 交换排序

主要思想:不断比较序列中两个元素的大小,并做一定的交换调整,直到整个序列有序。主要的算法有冒泡排序和快速排序。

  • 冒泡排序
    该算法的平均时间复杂度是O(n^2),空间复杂度为O(1),属于稳定排序。每趟排序都能定下一个元素的位置。以下为算法的实现代码:
 public static void BubbleSort(int[] array, int n) {    boolean flag;// 作为标记    for (int i = n - 1; i >= 0; i--) {// 每次遍历 确定一个最大元素 放在i处        flag = false;        int k;        for (int j = 0; j < i; j++) {            if (array[j] > array[j + 1]) {                flag = true;                k = array[j];                array[j] = array[j + 1];                array[j + 1] = k;            }        }        if (!flag)            break;        }    } 

从下标j=0开始,不断比较左右两个元素的大小,将大的元素放在右边,直到j=i,将最大的元素放在i处,之后i–,而j又从0开始判断。其中flag用于标记该趟比较时候已经有序,有序flag=false,停止遍历,结束。

  • 快速排序
    该算法的平均时间复杂度是O(nlogn),空间复杂度为O(logn),属于不稳定排序。每趟排序都能定下一个元素的位置。以下为算法的实现代码:
public static void QuickSort(int[] array, int n) {        Qsort(array, 0, n - 1);    }// 递归形式 划分后 分别排序public static void Qsort(int[] array, int low, int high) {  if (low < high) {    int pivotLoc = Partition(array, low, high);//求出枢轴的位置    Qsort(array, low, pivotLoc - 1);//根据枢轴划分左右,分别排序    Qsort(array, pivotLoc + 1, high);   }}// 一次划分,找出枢轴最后落下的i位置public static int Partition(int[] array, int low, int high) {    int pivot = array[low];// 子表第一个元素作为枢轴    while (low < high) {        while (low < high && array[high] >= pivot)            high--;//跟高位比较大小,直到碰到高位小的元素        array[low] = array[high];        while (low < high && array[low] <= pivot)            low++;//跟低位比较大小,直到碰到低位大的元素        array[high] = array[low];        }        array[low] = pivot;        return low;//返回枢轴的位置    }

首先定下一个枢轴,然后以其为标杆,将比该枢轴元素大的元素放置其右侧,而比它小的元素放置于其左侧。之后再分别对这两部分元素进行同样的操作。

3. 插入排序

主要思想:假定已存在一个元素,然后将剩余元素依次与其比较大小,比该元素大的放在其后面,若比该元素小,则继续往前比较,直到找到一个合适的位置插入。主要的算法有直接插入算法和希尔排序算法。

  • 直接插入算法
    该算法的平均时间复杂度是O(n^2),空间复杂度为O(1),属于稳定排序。以下为算法的实现代码:
public static void InsertSort(int[] array, int n) {    int k, j;    for (int i = 1; i < n; i++) {        if (array[i] < array[i - 1]) {            k = array[i];            for (j = i - 1; j >= 0 && array[j] > k; j--)                array[j + 1] = array[j];            array[j + 1] = k;        }    }}

从序列的第二个元素开始判断,分别与其前一元素进行比较,来确定要插入的位置。

  • 希尔排序算法
    该算法的平均时间复杂度是O(d),空间复杂度为O(1),属于不稳定排序。以下为算法的实现代码:
public static void ShellSort(int[] array, int n) {    int dk;// 增量    int k, j;    for (dk = n / 2; dk >= 1; dk = dk / 2) {        for (int i = dk; i < n; i++) {            if (array[i] < array[i - dk]) {                k = array[i];                for (j = i - dk; j >= 0 && array[j] > k; j -= dk)                    array[j + dk] = array[j];                array[j + dk] = k;            }        }    }}

希尔排序算法实际上是直接插入的改进版,加入了增量。

4. 归并排序

主要思想: 首先将序列中每个元素看成一个有序序列,然后不断归并相邻两个有序序列组成一个新的有序序列,直到将原始的整个序列变成有序序列,这种算法称为二路归并排序。该算法的平均时间复杂度为O(nlogn),空间复杂度为O(n),属于稳定排序。其算法的代码实现如下:

public static void MergeSort(int[] array, int n) {    MSort(array, 0, n - 1);}// 递归调用,进行分割和合并public static void MSort(int[] array, int low, int high) {    if (low < high) {        int mid = (low + high) / 2;        MSort(array, low, mid);        MSort(array, mid + 1, high);        Merge(array, low, mid, high);    }}public static void Merge(int[] array, int low, int mid, int high) {    int[] B = new int[high - low + 1];// 辅助数组B    int k = 0;    int i = low, j = mid + 1;    while (i <= mid && j <= high) {        if (array[i] < array[j])            B[k++] = array[i++];        else            B[k++] = array[j++];    }    while (i <= mid)//防止两个有序序列的元素个数不相等        B[k++] = array[i++];    while (j <= high)        B[k++] = array[j++];    // 将B中元素放回A中    for (int v = 0; v < k; v++)         array[low + v] = B[v];    }

5. 各种排序算法的比较

这里写图片描述

0 0
原创粉丝点击