作者 | 程序員小灰
責編 | 伍杏玲
"作者 | 程序員小灰
責編 | 伍杏玲
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){"
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){"
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){"
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){"
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){"
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
第二輪粗調(增量為2)之後:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
第二輪粗調(增量為2)之後:
最終排序結果:
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
第二輪粗調(增量為2)之後:
最終排序結果:
相同的元素5,在排序之後改變了次序,由此可見希爾排序是一個不穩定排序。
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
第二輪粗調(增量為2)之後:
最終排序結果:
相同的元素5,在排序之後改變了次序,由此可見希爾排序是一個不穩定排序。
【END】
隨著智能物聯迅速的興起,場景聯動越來越普遍,作為敲門磚的連接服務該如何實現?
360 資深工程師深度揭祕 360 IoT 雲平臺連接服務的技術框架實現細節、物聯網協議應用和多協議,多網絡的落地實踐以及連接服務未來的演進方向。
技術乾貨來襲!立即掃碼報名!
"作者 | 程序員小灰
責編 | 伍杏玲
————— 第二天 —————
————————————
讓我們先來回顧一下插入排序:
插入排序顧名思義,就是在排序的過程中,把數組的每一個元素按照大小關係,插入到前面有序區的對應位置。
比如下面數組中的元素3,按照大小關係,需要插入到前面有序區三個元素之前,而前面三個元素則相應向後挪動:
以此類推,插入排序一共會進行(數組長度-1)輪,每一輪的結果如下:
插入排序的平均時間複雜度是O(n^2)。這個排序算法並不複雜,但顯然並不是一個高效的排序算法。
那麼,怎樣可以對插入排序算法做出優化呢?我們不妨從插入排序的兩個特點入手:
1.在大多數元素已經有序的情況下,插入排序的工作量較小
這個結論很明顯,如果一個數組大部分元素都有序,那麼數組中的元素自然不需要頻繁地進行比較和交換。
2.在元素數量較少的情況下,插入排序的工作量較小
這個結論更加顯而易見,插入排序的工作量和n的平方成正比,如果n比較小,那麼排序的工作量自然要小得多。
如何對原始數組進行預處理呢?聰明的科學家想到了一種分組排序的方法,以此對數組進行一定的“粗略調整”。
所謂分組,就是讓元素兩兩一組,同組兩個元素之間的跨度,都是數組總長度的一半,也就是跨度為4。
如圖所示,元素5和元素9一組,元素8和元素2一組,元素6和元素1一組,元素3和元素7一組,一共4組。
接下來,我們讓每組元素進行獨立排序,排序方式用直接插入排序即可。由於每一組的元素數量很少,只有兩個,所以插入排序的工作量很少。每組排序完成後的數組如下:
這樣一來,僅僅經過幾次簡單的交換,數組整體的有序程度得到了顯著提高,使得後續再進行直接插入排序的工作量大大減少。這種做法,可以理解為對原始數組的“粗略調整”。
但是這樣還不算完,我們可以進一步縮小分組跨度,重複上述工作。把跨度縮小為原先的一半,也就是跨度為2,重新對元素進行分組:
如圖所示,元素5,1,9,6一組,元素2,3,8,7一組,一共兩組。
接下來,我們繼續讓每組元素進行獨立排序,排序方式用直接插入排序即可。每組排序完成後的數組如下:
此時,數組的有序程度進一步提高,為後續將要進行的排序鋪平了道路。
最後,我們把分組跨度進一步減小,讓跨度為1,也就等同於做直接插入排序。經過之前的一系列粗略調整,直接插入排序的工作量減少了很多,排序結果如下:
讓我們重新梳理一下分組排序的整個過程:
像這樣逐步分組進行粗調,再進行直接插入排序的思想,就是希爾排序,根據該算法的發明者,計算機科學家Donald Shell的名字所命名。
上面示例中所使用的分組跨度(4,2,1),被稱為希爾排序的增量,增量的選擇可以有很多種,我們在示例中所用的逐步折半的增量方法,是Donald Shell在發明希爾排序時提出的一種樸素方法,被稱為希爾增量。
public static void sort(int [] array){
//希爾排序的增量
int d=array.length;
while(d>1) {
//使用希爾增量的方式,即每次折半
d=d/2;
for(int x=0;x<d;x++) {
for(int i=x+d;i<array.length;i=i+d) {
int temp=array[i];
int j;
for(j=i-d;j>=0&&array[j]>temp;j=j-d) {
array[j+d]=array[j];
}
array[j+d]=temp;
}
}
}
}
public static void main(String [] args)
{
int array = {5,3,9,12,6,1,7,2,4,11,8,10};
sort(array);
System.out.println(Arrays.toString(array));
}
看看上面這個數組,如果我們照搬之前的分組思路,無論是以4為增量,還是以2為增量,每組內部的元素都沒有任何交換。一直到我們把增量縮減為1,數組才會按照直接插入排序的方式進行調整。
對於這樣的數組,希爾排序不但沒有減少直接插入排序的工作量,反而白白增加了分組操作的成本。
如何為希爾排序選擇更有效的增量方式呢?
為了保證分組粗調沒有盲區,每一輪的增量需要彼此“互質”,也就是沒有除1之外的公約數。
於是,人們相繼提出了很多種增量方式,其中最具代表性的是Hibbard增量和Sedgewick增量。
Hibbard的增量序列如下:
1,3,7,15......
通項公式 2^k-1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(3/2))
Sedgewick的增量序列如下:
1, 5, 19, 41, 109......
通項公式 9*4^k - 9*2^k + 1 或者 4^k - 3*2^k + 1
利用此種增量方式的希爾排序,最壞時間複雜度是O(n^(4/3))
關於這兩種增量方式的時間複雜度,有些需要很複雜的數學證明,有些是人們的大致猜想,大家暫時不用糾結。
上面數組當中,有兩個元素5,綠色的5在前,橙色的5在後。
假如我們按照希爾增量分組,第一輪粗調(增量為4)之後,綠色的元素5會跟元素4交換,換到橙色的5後面:
第二輪粗調(增量為2)之後:
最終排序結果:
相同的元素5,在排序之後改變了次序,由此可見希爾排序是一個不穩定排序。
【END】
隨著智能物聯迅速的興起,場景聯動越來越普遍,作為敲門磚的連接服務該如何實現?
360 資深工程師深度揭祕 360 IoT 雲平臺連接服務的技術框架實現細節、物聯網協議應用和多協議,多網絡的落地實踐以及連接服務未來的演進方向。
技術乾貨來襲!立即掃碼報名!
"