排序算法:(从小到大进行排序)
目录:
1、冒泡排序法:
冒泡排序法是最基本的排序算法,通过比较数组中相邻两个数的大小,如果右侧比左侧小则交换二者的位置,否则不动,假设有如下的数组:
那么,我们从第一个数和第二个数开始进行比较,因为左侧的数大于右侧的数,故二者做交换,交换后,我们比较第二个数和第三个数
因为左侧的数小于右侧的数,故不发生变化,依次向后比较,最后比较的是第8个数和第9个数,最终该数组中最大的数被我们移到了右侧,换而言之这个数已经来到了正确的位置上,第一趟的排序过程如下:
接下来,我们要进行n-1次这样的排列过程(最后只剩下一个元素的时候无需排列),便能完成最终的排序,由此可知,对于n个数来说,最坏的情况共需要排列n-1趟,那么对于这种算法来说,其时间复杂度是:
实际上我们可以对冒泡排序做一定的优化,假设在某一趟遍历中我们发现,没有出现交换的情况,也就是说此时数组已经是有序的,那么我们便没有必要继续遍历下去了,所以,实际上对于最好的的情况,也就是数组本身就是有序的,冒泡排序只需要进行n-1次比较即可,时间复杂度为O(n),最终代码实现如下:
#include <stdio.h>
int main() {
int arr[] = { 5,2,4,3,9,8,7,2,2,2 };
int len = sizeof(arr) / sizeof(int);
BubbleSort(arr, len);
}
void BubbleSort(int* arr, int len) {
for (int i = 1; i < len - 1; i++) {
int flag = 0;// 标志位——检测是否此时的数组已经成为有序数组
for (int j = 0; j < len - i; j++) {
if (arr[j] > arr[j + 1]) {
// 俩俩相邻比较
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = 1;
}
}
if (flag == 0) return;// 已经成为有序数组,无需再排列跳出即可
}
return;
}
2、选择排序法:
选择排序和冒泡排序的方法十分相近,其目的都是找到当前遍历的数组中的最值,并用它和端点值进行比较,如果不同的话则一定时比端点值大,因此交换二者的位置,反之如果二者不相等,要么是比端点大,要么是相等,假设有如下数组:
假设我们此时要进行从小到大的排序,那么我们令右侧为端点,那么首先我们需要找到从头到端点内的最大值,显然最大值是9,由于9比端点值6要大,故做交换,排序过程如下:
对于选择排序而言,其最大的优点在于,交换移动的次数很少,最多进行n-1次,但是无论对于最好的情况还是最差的情况,其需要进行比较的次数是一致的,故其时间复杂度为:
最终我们的代码实现如下:
#include <stdio.h>
void SelctSort(int* arr, int len);
int main() {
int arr[] = { 5,2,4,3,9,8,7,2,2,2 };
int len = sizeof(arr) / sizeof(int);
SelctSort(arr, len);
}
void SelctSort(int* arr, int len) {
for (int i = 0; i < len; i++) {
// 循环遍历当前列,找到最值
for (int j = i + 1; j < len; j++) {
// 最值与端值作比较
if (arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return;
}
3、插入排序:
插入排序的思想是把数组分为了有序列和无序列两部分,那么我们首先将数组分为有序组和无序组两部分,假如一个数组中只有一个元素,那么该数组本身就是有序的,故我们设第一个元素构成的数组为有序组,而其余部分为无序组,那么我们从无序组中取出首元素,将其插入在有序组的合适的位置即可,那么假设我们有如下数组:
那么此时我们取出无序组中的首元素,也就是1,和有序组的首元素进行比较,我们发现1>4,故我们需要把1的位置向前移动,为了不过与频繁的交换数组中的元素,故我们换一种方式方式完成移动,也就是在有序组向前遍历的过程中,如果需要继续移动的话,则把后面的值覆盖为当前值,假设此时的数组如下所示: