5月份感觉自己荒废了啊,竟然只写了一篇博文,确实要准备各种考试和作业,所以研究方面也没太多进展,上周和老板讨论的思路现在正在实现,也不知道效果行不行,科研还真不是件容易的事。
这周勉强开始看算法导论了,也没很细的看每一部分,主要是看算法的思想,排序算法又看了一遍,还是觉得快排这种平均性能的算法比较好。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。上面这一段是从百度百科摘录的,我的理解是快排比归并要好的原因是它实现了就地排序,不需要额外的空间来存储临时数组。并且快排的过程一种很直观的理解是选一个坑,然后进行填坑,最后把这个坑的元素填到新的空坑中,这样就能满足新位置的该元素前面的元素比改元素小,后面的元素比改元素大,这样用同样的方法去排序子数组,递归就可以完成全部的排序。代码还是别人写的比较经典,这里借鉴下:
<span style="font-size:14px;">void quick_sort(int s[], int l, int r)
{
if (l < r)
{
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if(i < j)
s[i++] = s[j];
while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}
</span>
堆排序实际上是选择排序的一种,简单选择排序的思想是每次从左至右扫描序列,记下最小值的位置,并且与没排序好的子数组中的第一个进行交换。堆排序其实也一样,在建的大根堆的基础上选择堆顶的元素作为最大值放在数组最后的位置,每次放之后重新保持堆的性质,然后继续取堆顶元素,这样就完成了排序。思路也挺简单,但虽然时间复杂度为O(nlgn),其实实际效果没快排好,可能是单位时间不一样(这个我也不是太清楚)。
还有几种非比较型的排序算法,主要是计数排序,基数排序,桶排序这三种方法,感觉思想都差不多,计数排序是基数排序的一个子过程。计数排序的思想是待排序数组为A,用一个辅助数组C[k+1](如果数组的数的大小在0~K)数组的每个值是统计原数组中小于等于该值的数的个数,用新的数组B保存排序结果。
<span style="font-size:14px;"> for(i=array_size-1; i>=0; i--)
{
value = A[i];
pos = C[value];
B[pos-1] = value;
C[value]--;
}</span>
其他几种排序在这里就不赘述了,别人讲的也比我好,真正理解排序算法的精髓才是关键,这还得自己去多体会。