1.选择排序
选择排序法(Selection Sort) 是对数组进行排序常用的一种简单直观的方法。
该方法通过多次循环,每次从待排序的元素中选出最小(或最大)的一个元素,存放在数组的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。从而实现将一个数组内的所有元素按大小升序或降序排序
如图所示:
话不多说,先上例题:
假设有一组待排序的数组a
该数组包含这些元素:2, 45, 6, 12, 87, 34, 103, 53, 25
现对其使用选择排序法进行升序排序
代码分析:
首先定义数组以及数组长度变量len
通过for循环
让循环控制变量i从数组的最后一项(len-1)开始
使用自定义的max函数返回数组a从0到第i项中最大值的下标。
得到最大值下标后,把该最大值放到此时数组的末尾,也就是第len-1项
下一次循环,i变成len-2,再得到从0到第i项中最大值的下标,再次将其放到第i项,也就是数组的倒数第二项。
依次循环下去,直到i等于1,循环结束
排序完成,最后遍历输出。
代码:
#include <stdio.h> int max(int a[], int n); int main() { int a[] = { 2, 45, 6, 12, 87, 34, 103, 53, 25 }; int len = sizeof(a) / sizeof(int); // 选择排序 for (int i = len - 1; i > 0; i--) { int maxid = max(a, i + 1); int t = a[maxid]; a[maxid] = a[i]; a[i] = t; } // 遍历输出 for (int i = 0; i < len; i++) printf("%d ", a[i]); printf("\n\n\n"); return 0; } int max(int a[], int n) // 返回数组a中最大值的下标; n表示该数组的长度 { int max = 0; for (int i = 0; i < n; i++) { if (a[i] > a[max]) max = i; } return max; }
运行结果:
程序运行成功。
2.冒泡排序
冒泡排序(Bubble Sort)也是对数组进行排序常用的方法,它通过多次循环,每次都从头到尾比较相邻两项的大小并进行位置调换来完成排序,也就是说,它要重复地遍历整个数组, 直到数组的每个元素都排序完毕。
如图所示:
同样还是上面的例题:
假设有一组待排序的数组a
该数组包含这些元素:2, 45, 6, 12, 87, 34, 103, 53, 25
现对其使用冒泡排序进行升序排序
代码分析:
先定义数组和数组的长度变量len,数组长度可以通过 (整个数组所占字节大小)/(单个元素所占字节大小) 来得到;
接着进入排序,使用两层嵌套循环,第一层的控制变量i表示遍历数组的次数,完成整个冒泡排序过程需要[数组长度-1]次,所以我们让它从1开始直至len-1;
第二层的控制变量 j 表示遍历到数组的第几个元素,j 从0开始直至len-2,比如当 j = 0时,比较第0项和第1项的大小,若后一项小于前一项,则交换它们的位置;
上述嵌套循环完成后,数组也就完成了排序。
代码:
#include <stdio.h> int main() { int a[] = { 2, 45, 6, 12, 87, 34, 103, 53, 25 }; int len = sizeof(a) / sizeof(int); // 冒泡排序 for (int i = 1; i < len; i++) { for (int j = 0; j < len-1; j++) { if (a[j + 1] < a[j]) { int t = a[j + 1]; a[j + 1] = a[j]; a[j] = t; } } } // 遍历输出 for (int i = 0; i < len; i++) printf("%d ", a[i]); printf("\n\n\n"); return 0; }
运行结果与选择排序法相同。
3.二分查找
问题引入:
现有上述按升序排序完的数组: 2, 6, 12, 25, 34, 45, 53, 87, 103;
要求定义一个函数,该函数可以返回某个指定整数(假设为34)在该数组中的下标。
代码分析:
定义三个记号left(左)、mid(中)、right(右),初始位置左记号在数组第0项,右记号在最后一项;
使用while循环,每次循环比较中记号所表示项与指定整数的大小关系,以判断是否进一步缩小范围或返回结果;
若范围缩小到左记号跑到右记号的右边还没找到指定整数,则结束循环,返回-1.
代码:
int search(int a[], int n, int x) // 传入参数:待查找数组a,数组长度n,查找指定整数x { int index = -1; // 返回值初始化为-1,若未找到指定整数则返回-1 // 二分查找法 int left, right, mid; // 定义左中右三个下标记号 left = 0; // 左记号初始位置为第0项 right = n - 1; // 右记号初始位置为最后一项 while (left < right) { // 当左记号不在右记号的左边时,查找过程结束,未找到指定整数,结束循环 mid = (left + right) / 2; if (a[mid] == x) { // 找到指定整数,将该下标传递给返回值index,并结束循环 index = mid; break; } else if (a[mid] < x) { // 若中记号所表示的项 小于 指定整数,则表明此时数组左半部分的所有项均小于指定整数 left = mid + 1; // 这时将左记号移至此时中记号的右一位,也就是将查找范围缩小到此时数组的右半部分 } else { // 反之则移动右记号,将范围缩小到左半部分 right = mid - 1; } } return index; }
运行结果:
在主函数中成功正确输出指定整数下标:4
总结:
二分查找法相较于一般的遍历查找法 循环次数更少,程序运行效率更高,不过待查找的数组一定得是有序的数组才可使用该方法。
END:)
注:1 2算法示意动图引用自菜鸟教程