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

原创 2017年01月03日 16:10:22

几种排序算法的整理

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

    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. 各种排序算法的比较

这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【大话数据结构】几种排序算法

这篇笔记主要写写几种常见的排序算法(C语言)。包括冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序、快速排序。

数据结构几种排序算法详解和总结(java版)

一、排序的概念: 1、设 n 个记录的序列为  { R1 , R2 , R3 , . . . , Rn} 其相应的关键字序列为  { K1 , K2 , K3, . . . , Kn } 若规定 1...

数据结构:几种排序算法的介绍。

老师布置了一套题目:关于冒泡排序优化。 想了一下,实在不知道怎么做,只会加一个flag变量,若序列已经有序,则不在判断。令我吃惊的是速度不仅没有加快,反而变忙了,我也是醉了。大概是因为fla...

【数据结构】几种常见的排序算法

一、排序算法的分类     下图是我掌握的一些排序算法,我将他们做了分类,当然,排序算法远不止这些。 本篇博客主要记录插入,选择,以及交换排序的冒泡排序,因为快排和归并算法相对复杂,所以,...

数据结构之排序算法整理(3)

选择排序

数据结构之排序算法整理(5)

归并排序类 归并paixu

数据结构之排序算法整理(1)

排序问题是各大IT公司必考的题目。 1.排序的对象--we
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)