題外話
很多人都認為(包括過去的筆者),排序演算法各種程式語言都有實現,我們就沒必要再去造輪子了,所以再更多的時候就會忽略它們的應用場景和思想。這裡,筆者的觀點是,改造的輪子還是要造的。
有乙個這樣的問題(後續就稱呼為topk問題):給定乙個陣列,返回前k個最小值,返回的陣列順序沒有要求,當然,k小於陣列長度。這其實是leetcode上一道標著「簡單」的題,然後很多網友直接調乙個排序介面就搞定了(包括筆者),效率還算高。但看到官方題解用了三種方法,分別是直接排序的,快排思想和堆的思想,突然發現我可能是誤解官方題目的意思了,哈哈。
其實在這裡,用快排和堆排序的思想就很好,一般來說我們直接排序的演算法複雜度為o(nlogn),而另兩種的複雜度為o(nlogk),先來說說快排吧。
快速排序
//快速排序
void
quicksort
(int arr,
int startindex,
int endindex)
int pivotindex = startindex;
std::cout<<
"startindex->"
<" endindex->"
int i = startindex +
1;i < endindex;
++i)
} std::cout<<
"pivotindex->"
else
}
在這裡,針對topk問題,因為並不需要分割點左右兩邊都是有序的,所以我們其實只要找到分割點為k就行了。**如下:
//快排思想解決topk問題
void
topkbyquicksort
(int arr,
int startindex,
int endindex,
int k)
int pivotindex = startindex;
std::cout<<
"startindex->"
<" endindex->"
int i = startindex +
1;i < endindex;
++i)
}swap
(arr[pivotindex]
,arr[startindex]);
if(pivotindex == startindex && pivotindex < endindex)
std::cout<<
"pivotindex->"
else
if(pivotindex > k)
}
其實還可以優化的,當k超過陣列長度的二分之一時,我們完全可以取反,可以轉化為找前len - k 的最大值問題,這樣就能保證topk問題的複雜始終不超過o(log n/2)。
堆排序主要是利用堆這個資料結構的特性——堆其實就是乙個陣列實現的完全二叉樹,堆中所有父節點的值均大於子節點。由於這個特性,我們可以利用堆來做很多事,堆排序就是乙個經典例子。因為堆的特性,堆頂節點的值要麼是最小的,要麼是最大的(這跟構建的堆型別有關,有最小堆和最大堆),所以,我們就可以不斷彈出堆頂元素並更新堆,直至堆的長度變為0,這樣就達到了排序的目的。然後這裡的topk問題跟堆排序的思想基本一致。附上c++實現**:
#include
#include
int heapsize =0;
intgetleftindex
(int index)
intgetrightindex
(int index)
void
swapvalue
(int
& a,
int& b)
void
adjugeheap
(std::vector<
int>
&vc,
int index)
int rightindex =
getrightindex
(index);if
(rightindex < heapsize && vc[rightindex]
< vc[lessindex])if
(lessindex == index)
else
}void
buildheap
(std::vector<
int>
& vc)
}int
popheap
(std::vector<
int>
& vc)
int temp = vc[0]
; vc[0]
= vc[heapsize---1
];adjugeheap
(vc,0)
;return temp;
}//刪除某個節點
unsigned
char
deleteheap
(std::vector<
int>
& vc,
int index)
vc[index]
= vc[heapsize---1
];adjugeheap
(vc,index)
;return rescode;
}void
insertheap
(std::vector<
int>
& vc,
int value)
}void
heapsort
(std::vector<
int>
& vc)
//堆排序
heapsize = temheapsize;
}void
topkbyheap
(std::vector<
int>
& vc,
int k)
for(
int i = k;i < heapsize;
++ i)}}
void
lo**c
(std::vector<
int>
&vc)
std::cout<}
這裡,跟快排一樣,堆排序思想解決topk問題演算法複雜度也是o(nlogk),k也可以始終小於n/2。
演算法是核心,程式設計是基礎。
希爾排序,堆排序,快速排序
插入排序的改進演算法,不穩定的排序演算法,空間複雜度為o 1 public static void shellsort int a 氣泡排序的改進演算法,不穩定的排序演算法 空間複雜度在o log2n 和o n 之間 時間複雜度在o n 和o n2 之間,平均時間複雜度為o nlog2n 而當陣列初...
希爾排序,快速排序,堆排序
最近在準備資料結構的考試,於是用部落格記錄下自己複習的過程。今天的內容是三種高階排序。希爾排序 當序列增量為incr k 2 t k 1 1時,時間複雜度為o n1.5 以序列增量分組,對每組進行大小調整。templatevoid shellinsert t elem,int n,int incr ...
排序(二) 快速排序 堆排序
一 排序分析 5 快速排序 時間複雜度 o nlog2n 有序 o n 2 空間複雜度 o log2n 演算法穩定性 不穩定 快速排序 分割槽 遞迴操作 固定位置選取基準法low 隨機選取 有序資料的優化 三分選取 優化 1 直接插入 少於100各元素 2 聚集基準位置法 取基準 分資料段 1 lo...