前言:
现在同学们对“排序算法关键字是什么”都比较着重,看官们都需要学习一些“排序算法关键字是什么”的相关文章。那么小编同时在网上收集了一些有关“排序算法关键字是什么””的相关内容,希望姐妹们能喜欢,朋友们一起来了解一下吧!如果插入排序(歪说基础算法6-1:魔法系列:我们一起搅动魔法锅,揭秘插入排序!)是我们的乌龟,那希尔排序就是兔子。尽管乌龟和兔子都属于同一类动物(排序算法),但它们的速度差别却大如天堂地狱之别。希尔排序是插入排序的一个版本,但它使用了一个巧妙的技巧来大大提高了排序速度。
魔法原理:什么是希尔排序?
希尔排序,也被称为“递减增量排序”,是由Donald Shell在1959年发明的。它的基本思想是对输入数组进行预排序,然后使用插入排序进行最后的排序。预排序是怎么进行的呢?它将数组分割成几个小的子序列,这些子序列是原数组的一部分,但它们的元素是原数组的几个特定间隔的元素。然后,对每个子序列进行插入排序。
你可能会问:“为什么要预排序?”好问题!预排序的目的是使数组“几乎有序”。在“几乎有序”的数组中,插入排序的性能可以达到接近线性时间。现在,你可能想知道,“几乎有序”是什么意思。好吧,当一个数组中任意i位置的元素大约在其最终排序位置的常数距离内时,我们就说这个数组是“几乎有序”的。
魔法实践:用案例理解希尔排序
让我们继续使用我们的魔法卡片。假设我们有一个乱序的魔法卡片数组[5, 3, 4, 7, 2, 8, 6, 9],我们要使用希尔排序对其进行排序。
我们首先选择一个增量,这个增量是我们划分子序列的步长。让我们选择增量为3,那么我们就有三个子序列:[5, 7, 6],[3, 2, 9]和[4, 8]。
我们对每个子序列进行插入排序。排序后的数组变为[3, 2, 4, 5, 7, 8, 6, 9]。
然后我们减小增量,让我们选择增量为2,那么我们就有两个子序列:[3, 4, 7, 6]和[2, 5, 8, 9]。我们再次进行插入排序,排序后的数组变为[2, 4, 3, 6, 5, 8, 7, 9]。
最后,我们将增量减小到1,即,我们只有一个子序列,它包含了所有的元素。我们再次进行插入排序,最终得到的数组为[2, 3, 4, 5, 6, 7, 8, 9]。这就是我们想要的结果!我们成功地使用希尔排序对魔法卡片进行了排序!
希尔排序的伪代码如下:
function shellSort(array) gap = array.length / 2 while gap > 0 for i = gap to array.length temp = array[i] j = i while j >= gap and array[j - gap] > temp array[j] = array[j - gap] j = j - gap array[j] = temp gap = gap / 2
希尔排序的时间复杂度是O(n^(3/2)),当n非常大时,其性能优于插入排序。尽管希尔排序在最坏的情况下可能需要进行多次的插入排序,但由于增量的选择和预排序的影响,实际上希尔排序通常要快得多。
希尔排序和插入排序的关键区别在于,希尔排序首先对间隔较大的元素进行排序,这样可以移动许多元素到正确的位置,大大减少了后续插入排序的工作量。最后当增量减少到1时,数组已经几乎有序,这时插入排序也会非常快。
那么,希尔排序是否就是最好的排序算法呢?不,不是的。尽管希尔排序在某些情况下可能非常高效,但它也有其局限性。例如,希尔排序并不稳定,也就是说,如果原数组中有两个相同的元素,希尔排序可能会改变它们的相对顺序。此外,希尔排序的时间复杂度也没有像快速排序或归并排序那样达到O(n log n)。
好了,下一步我们将实现一个希尔排序的C++程序。
#include <iostream>#include <vector>void shellSort(std::vector<int>& arr) { int n = arr.size(); // Start with a big gap, then reduce the gap for (int gap = n/2; gap > 0; gap /= 2) { // Do a gapped insertion sort for this gap size. for (int i = gap; i < n; i += 1) { // add arr[i] to the elements that have been gap sorted int temp = arr[i]; int j; // shift earlier gap-sorted elements up until the correct location for arr[i] is found for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) { arr[j] = arr[j - gap]; } // put temp (the original arr[i]) in its correct location arr[j] = temp; } }}int main() { std::vector<int> arr = {5, 3, 4, 7, 2, 8, 6, 9}; shellSort(arr); for(auto val : arr){ std::cout << val << " "; } return 0;}
这段代码首先定义了一个shellSort函数,该函数接受一个int类型的vector作为输入,并对其进行希尔排序。这个函数首先计算出一个gap值,然后对数组进行分组,对每个组进行插入排序。随着gap值的减小,数组的有序度逐渐提高,最后当gap为1时,我们就完成了整个数组的排序。
在main函数中,我们创建了一个待排序的int类型的vector,然后调用了shellSort函数进行排序。排序结束后,我们遍历这个vector并打印出每个元素,以验证排序结果。
这就是希尔排序的C++实现,希望你能从中学到一些新知识。
标签: #排序算法关键字是什么