您的位置:首页 > 理论基础 > 数据结构算法

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

2017-01-03 16:10 465 查看

几种排序算法的整理

选择排序

交换排序

插入排序

归并排序

各种排序算法的比较

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
);
}

/** 向下调整堆的算法
*  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);
}

// 递归形式 划分
cb89
后 分别排序
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. 各种排序算法的比较

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息