快速排序演算法 Partition函式 分析與拓展

2021-07-13 05:46:59 字數 4560 閱讀 6259

條件:如果陣列是有序陣列、部分有序陣列、或者區域性有序陣列,在這類陣列中進行查詢時,二分查詢較為常用。時間複雜度o(logn)。二分查詢的主要思路:設定兩個指標start和end分別指向陣列元素的首、尾,然後比較陣列中間結點arry[mid]和待查詢元素。如果待查詢元素小於中間元素,說明待查詢元素在陣列的前半段,那麼將end=mid-1,如果待查詢元素大於中間元素,說明該元素在陣列的後半段,將start=mid+1; 如果中間元素等於待查詢元素,那麼返回mid的值。

//統計乙個數字在已經有序的陣列中出現的次數。

int binary_search(vectordata, int len, int goal)

//沒找到

return -1;

}int getnumberofk(vectordata, int k)

} for (int i = index + 1; i < len; i++)

}} return count;

}void main()

; cout << getnumberofk(v, 3);

}//尋找第乙個

int getfirsttarget(vector& data, int target)

int pleft = 0;

int pright = length - 1;

while (pleft <= pright)

else  

pright = index - 1;

}else if (data[index] < target)

else  

}return -1;

}//尋找最後乙個

int getlasttarget(vector& data, int target)

int pleft = 0;

int pright = length - 1;

while (pleft <= pright)

else

pleft = index + 1;

}else if (data[index] < target)

else

}return -1;

}int getnumberofk1(vectordata, int k)

}return count;

}

在快速排序演算法中,我們隨機在陣列中選擇乙個數字,然後把比選中數字小的數字都排在它前面,比選中數字大的數字都排在它的後面。

//分割

int partition(vector& data, int length, int start, int end)

//int index = randominrange(start, end); //隨機產生乙個數為基準點進行劃分

//std::swap(data[index], data[end]);

int curdivision = start - 1;

for (int index = start; index < end; ++index)

}} ++curdivision;

std::swap(data[curdivision], data[end]);

return curdivision; //把基準元素放到最終位置上,並且返回其最終位置索引

}

快速排序:

//快速排序

void quicksort(vector& data, int length, int start, int end)

int index = partition(data, length, start, end); //由上述partition可知以最後乙個元素為基準元素

if (index > start)

if (index < end)

}

問題描述:

//陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。

//例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。

//如果不存在則輸出0。

採用上述的partition()函式來做的思想:利用partition函式「」跳躍獲得」」

中間元素。既然出現次數超過一半,那麼在排好序以後(利用partition函式並不需要把整個陣列都排序,所以說是「」跳躍獲得「」),位於中間位置上的元素必定是「出現次數」超過一半的數。

bool g_inputinvalidflag = false;

bool checkinvalid(const vector& data, int length) //檢查輸入是否有效

return g_inputinvalidflag;

}bool checkmorethanhalf(const vector& data, int length, int number) //檢查是否存在出現次數超過一半的數字

bool ismorethanhalf = true;

if (times * 2 <= length)

return ismorethanhalf;

}int morethanhalfnum_solution(vectornumbers) //查詢出現次數超過一半的數字

else

}int result = numbers[middle];

if (!checkmorethanhalf(numbers, length, result))

result = 0;

return result;

}

問題描述:

//輸入n個整數,找出其中最小的k個數。

//例如輸入4,5,1,6,2,7,3,8, 則最小的4個數字是1, 2, 3, 4。

採用上述的partition()函式來做的思想:利用partition函式「盡量快速地」把前k個「最終有序」數字放到指定位置上,仍舊是區域性排序,並不等到整個陣列都排序完成猜得到結果。(這種解法修改了初始陣列)

vectorgetleastnumbers_solution(vectorinput, int k) 

else

}for (int i = 0; i < k; i++)

output.push_back(input[i]);

} return output;

}//分割  

int partition(vector& data, int low, int high)

return low;    // 返回關鍵字所在位置  

}int findkth(vectora, int n, int k)

else

}return a[index];

}

void main()

; cout << "排序前vector:";

for (int i : v)

cout << i << " ";

quicksort(v, v.size(), 0, v.size() - 1);

cout << endl << "排序後vector:";

for (int i : v)

cout << i << " ";

cout << endl;

cout << endl << "出現次數超過一半的數是:";

拓展1的優化方案:時間複雜度o(n)

int morethanhalfnum_solution1(vectornumbers)   //查詢出現次數超過一半的數字

else if (numbers[i] == result)

else

}if (!checkmorethanhalf(numbers, length, result))

result = 0;

return result;

}

拓展2的優化方案:o(n*logk)

#include#include#include#includeusing namespace std;

//這種方法適合處理海量資料,比如在一億個數中選出前十個最小的數,

//我們做如下面的工作:設定集合中的元素降序排列,只需k個元素大小的結合

typedef multiset> intset; //關鍵:設定集合中的元素降序排列

typedef multiset>::iterator setite;

void getleastnumbers_solution1(const vector& input, intset& leastnums, int k)

else

}} }

}測試:

快速排序演算法裡的partition函式

快速排序演算法裡的partition函式用來解決這樣乙個問題 給定乙個陣列arr和陣列中任意乙個元素a,重排陣列使得a左邊都小於它,右邊都不小於它。實現 arr為陣列,start end分別為陣列第乙個元素和最後乙個元素的索引 povitindex為陣列中任意選中的數的索引 int partitio...

Partition函式實現的快速排序演算法

被傳值傳引用的問題還有一些雜事困擾了一下午,現在終於可以靜下心來寫部落格了。這個partition函式是我在 劍指offer 那本書上看到的,其實對應於快排是乙個單項掃瞄。這個函式在很多演算法題上都有應用,主要原理就是選定乙個參考值,然後將資料分成兩部分,左邊都是比它小的,右邊都是比它大的。然後把中...

快速排序中的partition函式詳解

快速排序的精髓就在partition函式的實現。我們構建兩個指標,將陣列分為三部分,黑色部分全部小於pivot,中間藍色部分都大於pivot,後面紅色部分未知。i指標遍歷整個陣列,只要它指向的元素小於pivot就交換兩個指標指向的元素,然後遞增。arr為陣列,start end分別為陣列第乙個元素和...