三、插入排序
我们怎么来实现一个插入排序呢
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置后
- 重复步骤2~5
当然有图就更直观啦
void insertionSort(int arr[], int len)
{
for (int i = 1; i < len; i++) {
int temp = arr[i];
int tempIndex = i;
for (int j = i-1; j >= 0; j--) {
if (arr[j] > temp)
{
arr[tempIndex] = arr[j];
tempIndex = j;
}
else
{
break;
}
}
arr[tempIndex] = temp;
}
}
复制代码
这段代码还可以再精简一下。不过意思就是这个意思了。哈哈。
插入排序的比较是从有序序列的末尾开始,依次向前比较,相等元素的前后顺序是不会改变的。所以插入排序是稳定的。
四、快速排序
我们先来看一张图
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot)
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
- 递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
简单的说,就是不断的把数组分为左边(小于基准点)和右边(大于等于基准点)的两个子数组。
void quickSort(int arr[], int startIndex , int len){
int left = startIndex;
int temp ;
for (int i = startIndex + len - 1; i > left; i--)
{
if (arr[i] < arr[startIndex])
{
for (int j = left; j < i ; j++) {
left = j;
if (arr[j] >= arr[startIndex])
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
break;
}
}
}
}
temp = arr[startIndex];
arr[startIndex] = arr[left];
arr[left] = temp;
if (left > startIndex) {
quickSort(arr, startIndex, left - startIndex );
}
if (left + 1 < startIndex + len - 1) {
quickSort(arr, left + 1, startIndex + len - left-1);
}
}
复制代码
(写得不好,下次优化?)
快速排序是不稳定的排序。不稳定的时间点发生在中心交换的时候。例如5 3 3 4 3 8 9 10 11
这个数组,最后5和3交换的时候,就打乱了3的顺序。
下次再见...