一、前言
其实排序对于前端工程师来说没有后端那么重要,不过理解排序的原理还是比较有用的。例如有些应用数据比较少量的就不需要用后台来排序,如果用php后端脚本等排序会增加后台的开销。放在前端岂不是更好,当然我们有一个前端的排序神器sort。当然也做了很多得优化,不过用sort排序还需要注意一点,sort默认不传参数时候的排序是按照字母顺序对数组中的元素进行排序,其实就是按照字符编码的顺序进行排序。
今天主要复习一下简单得排序,分别为冒泡排序、插入排序、选择排序,冒泡目前是我认为最简单的排序。
二、冒泡排序
先简单说一下冒泡排序的原理,其实就是比较两个相邻的数据,如果前一个比后一个大,就将两个数据进行交换。所以一趟排序过后把最大得数就会交换到最后面。也就类似于泡沫从低端上浮到最上面。当然我觉得叫冒泡也不是那么贴切拉。你也可以从最后一个开始比较,如果后一个比前一个小就进行交换,那个一趟排序过后最小的就泡到前面啦。相对于冒泡,这个就是下浮啦^^~,冒泡排序是稳定的。
5 7 9 2 8 4 原始数据
5 7 9 2 8 4 5和7比较不交换
5 7 9 2 8 4 7和9比较不交换
5 7 2 9 8 4 9和2比较需要交换
5 7 2 8 9 4 9和8比较需要交换
5 7 2 8 4 9 9和4比较需要交换
红色9经过一趟排序就跑到了最后面,这里想象一下。如果两个数相等,那么肯定不会交换位置,这种排序就是稳定排序。稳定排序就是2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。从上面的过程当中可以看出来其实就是把最大数的9排序放到最后。这时候其实我可以想象到。那么我们每次遍历可以找出最大得数,然后跟倒数第一的数交换位置,然后在找到第二大得数跟倒数第二的数交换位置,其实这是一种排序思想,就是选着排序。
先看一下冒泡排序的c语言代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void print(int a[],int n, int i){ 5 for(int j = 0; j < 8; j++){ 6 printf("%d ",a[j]); 7 } 8 printf(" "); 9 } 10 11 void bubbleSort(int a[], int n) 12 { 13 for(int i = 0; i < n ; i++) 14 { 15 for(int j = 0; j < n - i - 1; j++) 16 { 17 if(a[j] > a[j+1]) 18 { 19 int temp = a[j]; 20 a[j] = a[j+1]; 21 a[j+1] = temp; 22 } 23 } 24 } 25 } 26 27 28 int main() 29 { 30 int a[8] = {2,1,5,7,4,9,6,1}; 31 bubbleSort(a, 8); 32 print(a,8,8); 33 }
在看一下javascript代码:
1 function bubbleSort(arr){ 2 for(var i = 0; i < arr.length; i++){ 3 for(var j = 0; j < arr.length - i - 1; j++){ 4 if(arr[j] > arr[j+1]){ 5 var temp = arr[j] 6 arr[j] = arr[j+1]; 7 arr[j+1] = temp; 8 } 9 } 10 } 11 console.dir(arr); 12 } 13 14 var a = [1,3,4,5,4,5,6,7]; 15 bubbleSort(a);
仔细琢磨一下这个代码,其实就可以看出来,如果一次都没有交换的代码,那么肯定是已经排序好的了,那么可以做一个开关,例如如果某趟排序没有做任何交换,那么肯定是排序好的了,直接退出循环就好。
代码如下:
1 function bubbleSort(arr){ 2 var flag = true, 3 n = arr.length, 4 i = 0; 5 6 while(flag && i < n){ 7 flag = false; 8 for(var j = 0; j < n - i - 1; j++){ 9 if(arr[j] > arr[j+1]){ 10 var temp = arr[j] 11 arr[j] = arr[j+1]; 12 arr[j+1] = temp; 13 flag = true; 14 } 15 } 16 i++; 17 } 18 19 } 20 21 var a = [1,3,4,5,4,5,6,7]; 22 bubbleSort(a); 23 console.dir(a);
总之冒泡排序是一种比较低效率的排序,如果数规模很小时,可以采用。数据规模比较大时,最好用其他效率高的排序算法。
三、选择排序
选择排序原理就是每遍历一次找到其中的最小值然后跟第一个数据交换,接着在从第二个数据往后找到最小值跟第二个替换。当然也可以从中找到最大值跟最后一个交换,原理是是相同的。突然感觉跟冒泡有点类似啦~,不过选择排序是非稳定的。
5 7 9 2 8 4 原始数据
2 7 9 5 8 4 第一趟排序找到最小 2跟5交换
2 4 9 5 8 7 第二趟排序找到最小 4跟7交换
2 4 5 9 8 7 第三趟排序找到最小 9跟5交换
2 4 5 7 8 9 第四趟排序找到最小 7和9交换
2 4 5 7 8 9 第五趟排序没有交换
c语言代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void print(int a[],int n, int i){ 5 for(int j = 0; j < 8; j++){ 6 printf("%d ",a[j]); 7 } 8 printf(" "); 9 } 10 11 12 void selectSort(int a[], int n) 13 { 14 int i, j, min, temp; 15 for(i = 0; i < n - 1; i++) 16 { 17 min = i; 18 for(j = i + 1; j < n; j++) 19 { 20 if(a[min] > a[j]) 21 { 22 min = j; 23 } 24 } 25 if(min != i) 26 { 27 temp = a[min]; 28 a[min] = a[i]; 29 a[i] = temp; 30 } 31 32 } 33 } 34 35 int main() 36 { 37 int a[8] = {2,1,5,7,2,4,9,6}; 38 selectSort(a, 8); 39 print(a,8,8); 40 }
javascript代码
1 function selectSort(arr){ 2 var i = 0, j = 0, min = 0, temp, n = arr.length; 3 for(i = 0; i < n; i ++){ 4 min = i; 5 for(j = i + 1; j < n; j++){ 6 if(arr[min] > arr[j]){ 7 min = j; 8 } 9 } 10 if(i != min){ 11 temp = arr[i]; 12 arr[i] = arr[min]; 13 arr[min] = temp; 14 } 15 } 16 } 17 18 var a = [1,3,4,5,4,5,6,7]; 19 selectSort(a); 20 console.dir(a);
三、插入排序
最后一个简单排序插入排序,原理是将一个数据插入到已经排好序的有序数据中,形象的比喻就是扑克牌的抓拍,抓到一张牌首先要从后前到后扫一遍手里的牌,比较一下插入到合适的位置。插入排序是稳定的。
5 7 9 2 8 4 原始数据,以下红色是排序好的数据,首先拿出来一个数,就是插入好的数据。
5 7 9 2 8 4 7往5的序列里插入,正好在原来得位置不变
5 7 9 2 8 4 9往57的序列里插入,正好在原来得位置不变
2 5 7 9 8 4 2往579的序列里插入最前面,579向后移位
2 5 7 8 9 4 8往2579的序列里插入到7后面,9向后移位
2 4 5 7 8 9 4往25789的序列里插入到2后面,5789向后移位
c代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void print(int a[],int n, int i){ 5 for(int j = 0; j < 8; j++){ 6 printf("%d ",a[j]); 7 } 8 printf(" "); 9 } 10 11 void InsertSort(int a[], int n) 12 { 13 for(int i = 1; i < n; i++) 14 { 15 int key = a[i]; 16 int j = i - 1; 17 while(j >= 0 && a[j] > key) 18 { 19 a[j+1] = a[j]; 20 j--; 21 } 22 a[j+1] = key; 23 } 24 } 25 26 int main() 27 { 28 int a[8] = {2,1,5,7,2,4,9,6}; 29 InsertSort(a, 8); 30 print(a,8,8); 31 }
javascript 代码
1 function insertSort(arr){ 2 var n = arr.length, 3 i, 4 j, 5 key; 6 for(i = 1; i < n; i++){ 7 key = arr[i]; 8 j = i - 1; 9 while(j >=0 && key < arr[j]){ 10 arr[j+1] = arr[j]; 11 j--; 12 } 13 arr[j+1] = key; 14 } 15 } 16 var a = [1,3,4,5,4,5,6,7,0,8,11,65,88]; 17 insertSort(a); 18 console.dir(a);
插入排序跟后面的希尔排序有着类似的思路,希尔排序就是插入排序的升级,跳着插。以上三种都是比较简单得排序方法,下一篇主要复习一下快速排序、归并排序、希尔排序、堆排序,其中他们都用到了递归函数,快排、归并、和希尔分别用到了分冶法,分页法就是把一个规模为N的问题分成两个或多个较小的与原问题类型相同的子问题,通过对子问题的求解,并把子问题的解合并起来从而构成整个问题的解,即对问题各个击破,分而治之,其实跟数学归纳法类似。