排序應用 快速排序,堆排序

2021-10-04 12:50:07 字數 3360 閱讀 7496

題外話

很多人都認為(包括過去的筆者),排序演算法各種程式語言都有實現,我們就沒必要再去造輪子了,所以再更多的時候就會忽略它們的應用場景和思想。這裡,筆者的觀點是,改造的輪子還是要造的。

有乙個這樣的問題(後續就稱呼為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...