Quicksort
快速排序是对冒泡排序的一种改进。那么就不得不先说一下冒泡排序!
提出问题:给定的一个随机数组,将数组排好序输出。
一、解决思路:将数组第一个位置上的元素与其他所有元素一一对比,得到最小值并将其放到第一个位置;将数组第二位置上的元素与第三个到最后一个元素一一对比,得到最小值并将其放到第二个位置上;依次循环第三个、四个位置上一直到数组最后一个位置。便可得到排好的顺序。(思考:这是冒泡排序吗?先实现一下)
第一次写的代码如下:
通过查询资料、技术贴等等,又对其进行了代码优化,把自己的代码和别人的代码相对比,发现差距很大。由衷感慨:懂和写出来是两码事,而写出来和写好又是另外两码事!下面是大神的代码,我对自己的编码能力惭愧不已:
void betterFirst(){
int a[10] = {2,4,6,1,9,8,3,7,10,5};
for(int i=0;i<10;i++)
for(int j=i+1;j<10;j++)
if(a[i]>a[j])//这里是i和j
swap(&a[i],&a[j]);
}
ok,至此,确实已经实现了正确的排序。但是,还是那个问题:这是冒泡排序吗?从大学刚学C语言就开始学,我一直没弄清它与冒泡排序到底有什么区别。
二、下面我们来认识一下真正的冒泡。
冒泡思想:把这些数看成大小不一的泡,然后将最小的泡冒到最上面,其他大小依次排列;或者将最大的泡沉到最下面,剩下依次排列,一个道理。
将最小的泡冒到最上面思想:将最后位置的元素与倒第二位置的元素比较,若小于就交换,否则将倒第二元素和倒第三元素比较,规则依旧;倒第三元素和倒第四个元素相比较;依次运行下去,直到第二个元素和第一个元素比较为止。第一次循环结束,结果:得到一个最小值,并把它放在了第一个位置。
再进行第二次循环,同上,将最后位置的元素和倒第二位置元素比较,再将倒第二位置元素与倒第三位置元素比较,依次进行下去,由于第一次循环已经将最小值放在了第一个位置,所以这次循环只需要进行到第三个位置元素与第二个元素比较,第二次循环结束,结果:得到了次小的值,并将其放在了第二个位置。
依次进行循环,最后一轮比较最后一个元素和倒第二个元素。至此,排序完成。代码如下:
void bubblesort(){
int a[10] = {2,4,6,1,9,8,3,7,10,5};
for(int i=0;i<10;i++)
for(int j=9;j>i;j--)
if(a[j]<a[j-1])//这里是j和j-1
swap(&a[j],&a[j-1]);
}
将最大的泡沉到最下面:只是从第一个元素开始,依次两两(此处两两是指位置一和二、二和三、三和四等,很多人在此处容易混淆)比较,将最大元素放到最后位置,依次循环,不再重复。代码如下:
void bubblesort2(){
int a[10] = {2,4,6,1,9,8,3,7,10,5};
for(int i=9;i>=0;i--)
for(int j=0;j<i;j++)
if(a[j]>a[j+1])
swap(&a[j],&a[j+1]);
}
这个版本的for循环反过来写的方式比较常见。
三、区别到底在哪呢?
第一:方法一依次循环,是固定一个位置不动,将该位置的元素依次与后面的其他元素相比较,一次遍历后,这个位置上就是最小/大值;冒泡是从后到前两两(上面已经解释)比较,是流动性的比较。其实说到底,我写的这个是选择排序!!!
第二:方法一每次循环虽然都选择了未排序中的最小的元素,并放在了适当位置,但是仍将本来比较小的元素放到了后面去了,而冒泡只把小元素提前,不会发生上述情况。
其实无论是冒泡排序还是选择排序都是可以优化的!有机会就补充上。
Note:注意数组越界问题,即for循环中要不要减一什么的,我还不是很清楚。
参考:
1:王道--《数据结构》
2、《算法导论》
3、百度百科