关于排序算法有如下分类
常用的几种排序算法有以下几个:
1.冒泡排序(Bubble Sort):
通过比较相邻元素的大小,依次交换相邻元素的位置,直到所有元素按照从小到大(或从大到小)的顺序排列。
冒泡排序是一种基本的排序算法,它的基本思想是通过不断比较相邻的两个元素,将较大(或较小)的元素向后交换,从而达到排序的目的。具体实现如下:
1.比较相邻的元素。如果第一个比第二个大,就交换它们两个。
2.对每一对相邻的元素进行比较,从第一对到最后一对。这样,最后的元素应该是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上述步骤,直到没有任何一对数字需要比较。
下面是C++实现冒泡排序的 Java 代码实现
下面是Java实现冒泡排序的 Java 代码实现
public static void bubbleSort(int[] arr) {
int temp;//临时变量
boolean flag;//标识变量,表示是否进行过交换
//外层循环控制排序趟数
for (int i = 0; i < arr.length - 1; i++) {
flag = false;//每次开始排序前,都设置flag为未排序过
//内层循环控制每一趟排序多少次
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {//如果前面的数比后面的数大,则交换
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = true;//只要有交换,flag就置为true
}
}
if (!flag) {//如果没有交换过元素,则已经有序,退出循环
break;
}
}
}
2.插入排序(Insertion Sort):
将一个元素插入到已排好序的数组中,使得插入后的数组仍然有序。
当我们使用插入排序算法时,我们将一个元素插入到已经排好序的数组中,使得插入后的数组仍然有序。假设我们在排序过程中,待排序的数组L[1...n]在某个时刻的状态如下:
我们需要将元素L(i)插入到已经有序的子序列L[1...i-1]中。为了完成这个操作,我们需要执行以下步骤:
- 查找L(i)在L[1...i-1]中的插入位置k。
- 将L[k...i-1]中的所有元素依次后移一个位置。
- 将L(i)复制到L(k)。
为了实现对数组L[1...n]的排序,我们可以将L(2)~L(n)依次插入到前面已经排好序的子序列中,初始时,我们可以将L[1]视为已经排好序的子序列。上述操作执行n-1次就能得到一个有序的数组。插入排序通常采用就地排序的方式,因此空间复杂度为O(1)。在从后向前的比较过程中,我们需要反复将已经排好序的元素逐步向后移动,为新元素提供插入空间。
以下是插入排序算法的C语言和Java代码实现,附有注释和讲解:
C语言代码实现:
#include <stdio.h>
void insertion_sort(int arr[], int n) {
int i, j, key;
for (i = 1; i < n; i++) {
key = arr[i];
j = i - 1;
// 将比key大的元素向后移动,为key腾出位置
while (j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
int main() {
int arr[] = {5, 2, 4, 6, 1, 3};
int n = sizeof(arr) / sizeof(arr[0]);
insertion_sort(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
Java代码实现:
public class InsertionSort {
public static void insertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
// 将比key大的元素向后移动,为key腾出
while (j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
public static void main(String[] args) {
int[] arr = {5, 2, 4, 6, 1, 3};
insertionSort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
注释和讲解:
在这两份代码中,我们都定义了一个名为insertion_sort
(C语言)或insertionSort
(Java)的函数来实现插入排序算法。在函数内部,我们使用了两个循环来实现排序。外层循环从第二个元素开始,依次将每个元素插入到前面已经排好序的子序列中。内层循环则用来将比当前元素大的元素向后移动,为当前元素腾出位置。
在C语言代码中,我们使用了一个while循环来将比当前元素大的元素向后移动。当找到一个比当前元素小的元素时,我们就将当前元素插入到这个元素的后面。在Java代码中,使用了一个for循环来实现相同的功能。当找到一个比当前元素小的元素时,我们就将当前元素插入到这个元素的后面。
在插入排序算法中,我们需要使用两个循环来完成排序,因此时间复杂度为O(n^2)。但是,由于插入排序算法具有就地排序的特点,因此空间复杂度为O(1)。
3.选择排序(Selection Sort):
每次选择数组中最小(或最大)的元素,将其放在数组的起始位置,然后再在剩余的元素中选择最小(或最大)的元素,放在已排序元素的末尾,直到所有元素有序。
假设排序元素为L【1,2.....n】 括号中代表元素次序1就是第一个元素,n就是第n各元素。
选择排序的基本思想是从第一个元素开始依次与其余元素对比,比值小则换位,然后取第二个元素依次向后继续比较大小,与之小则换位。选择排序的每一轮都会选择未排序序列中的最小元素,将其与未排序序列的第一个元素进行交换,从而不断缩小未排序序列的范围。在上面的例子中,选择排序的第一轮中,4和序列中的其他元素进行比较,找到最小的元素1,然后将4和1进行交换,因此4与1进行了交换。
#include <stdio.h>
void selection_sort(int arr[], int len) {
for (int i = 0; i < len - 1; i++) { // 外层循环控制排序轮数
int min_index = i; // 记录最小值的下标
for (int j = i + 1; j < len; j++) { // 内层循环查找最小值
if (arr[j] < arr[min_index]) {
min_index = j;
}
}
if (min_index != i) { // 如果最小值不是当前位置,则交换两个位置的元素
int temp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = temp;
}
}
}
int main() {
int arr[] = { 5, 3, 8, 4, 2, 7, 1, 6 };
int len = sizeof(arr) / sizeof(arr[0]);
selection_sort(arr, len);
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
Java的选择排序实现:
public class SelectionSort {
public static void selectionSort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) { // 外层循环控制排序轮数
int minIndex = i; // 记录最小值的下标
for (int j = i + 1; j < len; j++) { // 内层循环查找最小值
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) { // 如果最小值不是当前位置,则交换两个位置的元素
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
public static void main(String[] args) {
int[] arr = {5, 3, 8, 4, 2, 7, 1, 6};
selectionSort(arr);
for (int i : arr) {
System.out.print(i + " ");
}
System.out.println();
}
}
4快速排序(Quick Sort):
是一种高效的排序算法,它采用分治的思想,将一个大问题分解成若干个小问题来解决。快速排序的基本思想是:选择一个基准元素,将数组中小于基准元素的元素放在基准元素的左边,将大于基准元素的元素放在基准元素的右边,然后递归地对左右两个子数组进行排序,最终将整个数组排序。
快速排序的具体实现过程如下:
- 选择一个基准元素,一般选择第一个元素或者最后一个元素;
- 将数组中小于基准元素的元素放在基准元素的左边,大于基准元素的元素放在基准元素的右边;
- 对左右两个子数组分别递归地进行快速排序,直到子数组的长度为1或0。
快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn),是一种非常高效的排序算法。
以下是快速排序的C语言实现,附有注释和讲解:
#include <stdio.h>
void quick_sort(int arr[], int left, int right) {
if (left >= right) { // 如果左右指针相遇,则返回
return;
}
int i = left, j = right, pivot = arr[left]; // 初始化左右指针和基准元素
while (i < j) {
while (i < j && arr[j] >= pivot) { // 从右往左找第一个小于基准元素的数
j--;
}
if (i < j) {
arr[i++] = arr[j]; // 将该数放到左边
}
while (i < j && arr[i] < pivot) { // 从左往右找第一个大于等于基准元素的数
i++;
}
if (i < j) {
arr[j--] = arr[i]; // 将该数放到右边
}
}
arr[i] = pivot; // 将基准元素放到正确的位置
quick_sort(arr, left, i - 1); // 对左边的序列进行快速排序
quick_sort(arr, i + 1, right); // 对右边的序列进行快速排序
}
int main() {
int arr[] = { 5, 3, 8, 4, 2, 7, 1, 6 };
int len = sizeof(arr) / sizeof(arr[0]);
quick_sort(arr, 0, len - 1);
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
c复制代码
注释:
void quick_sort(int arr[], int left, int right)
:快速排序函数,参数包括待排序数组、左指针和右指针。if (left >= right)
:如果左右指针相遇,则返回。int i = left, j = right, pivot = arr[left]
:初始化左右指针和基准元素。while (i < j)
:当左右指针未相遇时,进行以下操作:
while (i < j && arr[j] >= pivot)
:从右往左找第一个小于基准元素的数。if (i < j)
:如果找到了,则将该数放到左边。while (i < j && arr[i] < pivot)
:从左往右找第一个大于等于基准元素的数。if (i < j)
:如果找到了,则将该数放到右边。arr[i] = pivot
:将基准元素放到正确的位置。quick_sort(arr, left, i - 1)
:对左边的序列进行快速排序。quick_sort(arr, i + 1, right)
:对右边的序列进行快速排序。
快速排序的时间复杂度为O(nlogn),是一种高效的排序算法。
以下是基础的快速排序的Java实现代码,同样加上了注释和讲解:
public class QuickSort {
public static void main(String[] args) {
int[] arr = {3, 1, 5, 2, 4, 9, 7, 6, 8}; // 定义一个包含9个元素的整型数组
quickSort(arr, 0, arr.length - 1); // 调用快速排序算法对数组进行排序
System.out.print("Sorted integers: "); // 输出排序后的整数
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " "); // 依次输出数组中的每个元素
}
}
/**
* 快速排序算法
* @param arr 待排序的数组
* @param left 数组的左边界
* @param right 数组的右边界
*/
public static void quickSort(int[] arr, int left, int right) {
if (left >= right) { // 如果左边界大于等于右边界,直接返回
return;
}
int i = left, j = right; // 定义两个指针i和j,分别指向数组的左右两端
int pivot = arr[left]; // 选择第一个元素作为基准元素
while (i < j) { // 循环执行以下操作,直到i >= j
while (i < j && arr[j] >= pivot) { // 从右向左找到第一个小于基准元素的元素
j--;
}
if (i < j) { // 如果i < j,将该元素移到左边
arr[i++] = arr[j];
}
while (i < j && arr[i] < pivot) { // 从左向右找到第一个大于等于基准元素的元素
i++;
}
if (i < j) { // 如果i < j,将该元素移到右边
arr[j--] = arr[i];
}
}
arr[i] = pivot; // 将基准元素放到正确的位置上
quickSort(arr, left, i - 1); // 对左边的子数组进行快速排序
quickSort(arr, i + 1, right); // 对右边的子数组进行快速排序
}
}
在上面的代码中,我们使用了递归的方式来实现快速排序。在快速排序算法中,我们首先选择一个基准元素,将数组中小于基准元素的元素放在基准元素的左边,大于基准元素的元素放在基准元素的右边。然后,我们对左右两个子数组分别递归地进行快速排序,直到子数组的长度为1或0。
需要注意的是,在快速排序算法中,我们使用了两个指针i和j来遍历数组,i指向数组的左端,j指向数组的右端。在每一轮循环中,我们先从右向左找到第一个小于基准元素的元素,然后从左向右找到第一个大于等于基准元素的元素,将它们交换位置。最终,基准元素就被放到了正确的位置上。
填坑法是一种基于快速排序的优化算法,它的思路是:在快速排序中,我们需要将小于基准元素的元素放在基准元素的左边,大于基准元素的元素放在基准元素的右边,这样的话,每次交换都需要移动多个元素,效率较低。因此,我们可以将交换操作转化为填坑操作,即先将基准元素保存到一个临时变量中,然后将空出来的位置填上小于基准元素的元素,最后将基准元素填到空出来的位置上。这样,每次交换只需要移动一个元素,效率更高。
以下是快速排序(填坑法)的Java实现代码,同样加上了注释和讲解:
public class QuickSort {
public static void main(String[] args) {
int[] arr = {3, 1, 5, 2, 4, 9, 7, 6, 8}; // 定义一个包含9个元素的整型数组
quickSort(arr, 0, arr.length - 1); // 调用快速排序算法对数组进行排序
System.out.print("Sorted integers: "); // 输出排序后的整数
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " "); // 依次输出数组中的每个元素
}
}
/**
* 快速排序算法(填坑法)
* @param arr 待排序的数组
* @param left 数组的左边界
* @param right 数组的右边界
*/
public static void quickSort(int[] arr, int left, int right) {
if (left >= right) { // 如果左边界大于等于右边界,直接返回
return;
}
int i = left, j = right; // 定义两个指针i和j,分别指向数组的左右两端
int pivot = arr[left]; // 选择第一个元素作为基准元素
while (i < j) { // 循环执行以下操作,直到i >= j
while (i < j && arr[j] >= pivot) { // 从右向左找到第一个小于基准元素的元素
j--;
}
if (i < j) { // 如果i < j,将该元素填到左边的空位上
arr[i] = arr[j];
i++;
}
while (i < j && arr[i] < pivot) { // 从左向右找到第一个大于等于基准元素的元素
i++;
}
if (i < j) { // 如果i < j,将该元素填到右边的空位上
arr[j] = arr[i];
j--;
}
}
arr[i] = pivot; // 将基准元素填到正确的位置上
quickSort(arr, left, i - 1); // 对左边的子数组进行快速排序
quickSort(arr, i + 1, right); // 对右边的子数组进行快速排序
}
}
在填坑法的实现中,我们使用了两个指针i和j来遍历数组,i指向数组的左端,j指向数组的右端。在每一轮循环中,我们先从右向左找到第一个小于基准元素的元素,然后将它填到左边的空位上;然后从左向右找到第一个大于等于基准元素的元素,将它填到右边的空位上。最终,基准元素就被填到了正确的位置上。
5.归并排序(Merge Sort):
归并排序是一种基于分治思想的排序算法。它的基本思想是将待排序的序列分成若干个子序列,分别进行排序,然后再将排好序的子序列合并成一个有序的序列。归并排序的主要过程可以分为两个步骤:
分割:将待排序的序列从中间分成两个子序列,再对子序列进行分割,直到每个子序列只有一个元素为止。
合并:将两个已经排好序的子序列合并成一个有序的序列,再将多个有序的子序列合并成一个完整的有序序列。
归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。它是一种稳定的排序算法,适用于各种数据类型的排序。但是,归并排序需要额外的空间来存储分割后的子序列,因此在排序大规模数据时,可能会出现空间不足的问题。
C语言实现:
#include <stdio.h>
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// 创建两个临时数组
int L[n1], R[n2];
// 将数据复制到临时数组中
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
// 合并临时数组
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
// 处理剩余元素
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
// 递归分解左右两部分
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
// 合并左右两部分
merge(arr, l, m, r);
}
}
int main() {
int arr[] = { 38, 27, 43, 3, 9, 82, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
Java实现:
public class MergeSort {
public static void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// 创建两个临时数组
int L[] = new int[n1];
int R[] = new int[n2];
// 将数据复制到临时数组中
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
// 合并临时数组
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
// 处理剩余元素
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
public static void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
// 递归分解左右两部分
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
// 合并左右两部分
merge(arr, l, m, r);
}
}
public static void main(String args[]) {
int arr[] = { 38, 27, 43, 3, 9, 82, 10 };
int n = arr.length;
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
6.堆排序(Heap Sort):
将数组看成一颗完全二叉树,将其转换为一个大根堆或小根堆,然后依次取出堆顶元素,将其放在已排序元素的末尾,直到所有元素有序。
堆排序(Heap Sort)是一种基于完全二叉树的排序算法,其基本思想是将待排序的数组看成一颗完全二叉树,然后将其转换为一个大根堆或小根堆。在大根堆中,每个父节点的值都大于等于其子节点的值;在小根堆中,每个父节点的值都小于等于其子节点的值。堆排序的基本步骤如下:
将待排序的数组转换为一个大根堆或小根堆。
取出堆顶元素,将其放在已排序元素的末尾。
调整剩余元素,使其仍然成为一个大根堆或小根堆。
重复步骤2和步骤3,直到所有元素有序。
具体实现过程如下:
将待排序的数组转换为一个大根堆或小根堆。
取出堆顶元素,将其放在已排序元素的末尾。
调整剩余元素,使其仍然成为一个大根堆或小根堆。
重复步骤2和步骤3,直到所有元素有序。
堆排序的时间复杂度为O(nlogn),空间复杂度为O(1)。由于堆排序需要进行大量的数据移动,因此其常数项比较大,不适合处理小规模的数据。
C语言实现:
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
void heapify(int arr[], int n, int i) {
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < n && arr[l] > arr[largest])
largest = l;
if (r < n && arr[r] > arr[largest])
largest = r;
if (largest != i) {
swap(&arr[i], &arr[largest]);
heapify(arr, n, largest);
}
}
void heapSort(int arr[], int n) {
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main() {
int arr[] = { 38, 27, 43, 3, 9, 82, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
heapSort(arr, n);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
Java实现:
public class HeapSort {
public static void swap(int arr[], int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void heapify(int arr[], int n, int i) {
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < n && arr[l] > arr[largest])
largest = l;
if (r < n && arr[r] > arr[largest])
largest = r;
if (largest != i) {
swap(arr, i, largest);
heapify(arr, n, largest);
}
}
public static void heapSort(int arr[], int n) {
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--) {
swap(arr, 0, i);
heapify(arr, i, 0);
}
}
public static void main(String args[]) {
int arr[] = { 38, 27, 43, 3, 9, 82, 10 };
int n = arr.length;
heapSort(arr, n);
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}