数据结构和算法自学之排序算法(一)
排序算法可以说是最基本的算法,希望通过自己再写一遍加强记忆。
一.冒泡排序
首先说下冒泡排序,因为排序过程很像气泡从水底一颗一颗冒出来,形象生动的叫冒泡排序,主要过程就是从头开始检索,一一比较,将比较的两者最大的放在后面,循环完毕排序结束。
举个例子:现有数组2,3,7,1,5,那么冒泡排序过程为:
第一轮:2<3,不变,现在数组为2,3,7,1,5
第二轮:3<7,不变,数组为2,3,7,1,5
第三轮:7>1,互换,数组为2,3,1,7,5
第四轮:7<5,互换,数组为2,3,1,5,7
一轮过后,最大值被换到了最后,然后循环n次(数组长度),排序完成,代码如下:
void BubbleSort(int arr[],int len) { int i, j = 0; int change = 0; for (i = 0; i < len;++i) { //外面这层循环用来将整个数组全部从小到大排序 for (j = 0; j < len - i - 1;++j) { //里面这层循环将最大值放到最后 if (arr[j]>arr[j+1]) { change = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = change; } } } }
冒泡法还有着一种可以优化的版本,如果内循环一轮下来,没有任何交换出现,证明后面已经排序完成,可以直接跳出循环,所以在这里添加一个标志符号,代码如下:
void BubbleSort(int arr[], int len) { int i, j = 0; int change = 0; bool flag = true; //表示排序还没有完成 while (flag) { for (i = 0; i < len; ++i) { //外面这层循环用来将整个数组全部从小到大排序 if (!flag) break; flag = false; for (j = 0; j < len - i - 1; ++j) { //里面这层循环将最大值放到最后 if (arr[j] > arr[j + 1]) { flag = true; //只要有交换就让外循环继续下去,否则就表明排序完成 change = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = change; } } } } }
二.快速排序
这个是用得最多的排序,因为平均效果表现最好,所以面试问到的几率会大很多,主要原理是,在一组数中随机选择一个数,将比这个数小的放在左边,将比这个数大的放在右边,然后再把子数组递归的采用同样的原理分组,直到不能分为止,一般我们就选第一个数作为初始基准,下面以6,1,2,7,9,3,4,5,10,8为例子,
第一轮:以6为基准,7与5交换,6,1,2,5,9,3,4,7,10,8
第二轮:以6为基准,9与4交换,6,1,2,5,4,3,9,7,10,8
第三轮:以6为基准,9位置比3位置后,这时后面已经分为两个子数组,且前面小于6,后面大于6,6与3交换,3,1,2,5,4,6,9,7,10,8
第四轮:前后两个子数组分别重复前三轮步骤
下面代码选自数据结构书上给的参考:
int pa(int arr[], int low,int high) { int pivit = arr[low]; //基准点 while (low<high) { while (low < high&&arr[high] >= pivit) {//从后往前检索,找到比基准点小的值,交换 --high; } arr[low] = arr[high]; while (low < high&&arr[low] <= pivit) {//从前往后检索,找到比基准点大的值,交换 ++low; } arr[high] = arr[low]; } arr[low] = pivit;//将基准点移到分割处 return low; } void QuickSort(int arr[],int low,int high) { if (low<high) { int pivit = pa(arr, low, high); QuickSort(arr, low, pivit - 1);//分出来的左子数组 QuickSort(arr, pivit + 1, high);//分出来的右子数组 } }