排序算法之选择排序
我们经常能遇到这样的问题,让你对一串数据进行排序,比如对一个数组,对顺序表等等进行排序。排序的方法有很多,你可以任意选择,只要能达到人家所要求的效果。一说到排序,对我来说最熟悉的就是冒泡排序,对于冒泡排序只要你掌握好了两个循环的条件其实很简单,今天我们谈谈另外一种排序算法:选择排序。
首先我们来说说选择排序的原理,我们还是要用两层for循环,外循环代表循环的次数,内循环是每次循环进来还要比较的次数。请看下面的图:首先我们把数组的第一个位置也就是位置0设为maxpos和minpos,然后再用一个循环进行数组内内容的比较,如果有比maxpos位的数大的,则更正我们的maxpos,这样比较完一次我们可以找到存最大的数的一个位置,比如下图中,我们最后找到了存放5的位置,也就是位置4,则maxpos=4.我下面的程序是改进了之后的选择排序,就是在进行比较的时候,同时更正minpos的值,这样我们的外层循环就被简化为原来次数的一半。
当一次比较完成后,我们就进行交换,假如现在是升序排序。把maxpos上的值和最右边位置的值进行交换,把minpos上的值和最右边位置的值进行交换。从而达到排序的效果。
但是我这样优化了之后也会存在一个问题,就是一次更正后要对maxpos上的值和minpos上的值分别交换到需要的位置上,那么如果刚好我maxpos上的值要交换的位置刚好就是我的minpos,那么我们在交换的时候就会把本来minpos上的值换走了,等你在对minpos上的值进行移动的时候肯定就不是我们想要的结果了。比如下面的情况:内循环完成之后,得到的maxpos是0,minpos是3,然后如果不进行别的处理,最大值5要被我和最右边位置的1进行交换,之后minpos上的值就变成5了,接下来的交换肯定就不对了。
所以在进行交换前我们就要进行判断,如果存在这样的问题,就把此时的maxpos和minpos上的值交换,同时也把minpos和maxpos进行交换。
下面是选择排序的程序代码,红色部分就是判断上面所述的特殊情况进行的处理。自己写的,肯定有很多地方比较麻烦希望见谅,大家有什么好的建议可以提出。
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include<assert.h> 4 #include<string.h> 5 #include<windows.h> 6 7 void selectsort(int *str,int len) 8 { 9 int maxpos = 0; 10 int minpos = 0; 11 int i = 0,j = 0; 12 assert(str); 13 for (; i < len / 2; i++) 14 { 15 maxpos = i, minpos = i; 16 for (j = i + 1; j < len-i; j++) 17 { 18 if (str[j]>str[maxpos]) 19 maxpos = j; 20 if (str[j] < str[minpos]) 21 minpos = j; 22 } 23 if (len - i - 1 == minpos) 24 { 25 int tmp = str[maxpos]; 26 int tmp1 = maxpos; 27 str[maxpos] = str[minpos]; 28 str[minpos] = tmp; 29 maxpos = minpos; 30 minpos = tmp1; 31 } 32 if (len - i - 1 != maxpos) 33 { 34 int temp = str[maxpos]; 35 str[maxpos] = str[len - i - 1]; 36 str[len - i - 1] = temp; 37 } 38 if (i != minpos) 39 { 40 int temp1 = str[minpos]; 41 str[minpos] = str[i]; 42 str[i] = str[minpos]; 43 } 44 } 45 } 46 47 int main() 48 { 49 int i = 0; 50 int str[] = { 1, 3, 4, 7, 2, 4, 6, 8 }; 51 int len = sizeof(str) / sizeof(str[0]); 52 selectsort(str,len); 53 for (; i < len; i++) 54 { 55 printf("%d ", str[i]); 56 } 57 58 system("pause"); 59 return 0; 60 }