對數組進行排序
Given an array of integers nums, sort the array in ascending order.
Example 1:
Input: nums = [5,2,3,1]
Output: [1,2,3,5]
Example 2:
Input: nums = [5,1,1,2,0,0]
Output: [0,0,1,1,2,5]
在leetcode上練習了一些與數組相關的題目,之前用到排序的時候都是直接調用STL中的算法,這次自己實現一下排序的算法。分別使用:快速排序(代碼簡潔)、簡單選擇排序(代碼簡短)、直接插入排序、堆排序。
題意:此題可以使用多種排序算法進行解答,算是數據結構中的基礎題目。
方法:分別嘗試使用簡單選擇排序、直接插入排序、快速排序方法來解決,但是由於簡單選擇排序和直接插入排序的時間複雜度比較高,沒有通過所有的測試用例。
class Solution {
public:
vector<int> sortArray(vector<int>& nums) {
// selectSort(nums);
// insertSort(nums);
// quickSort(nums,0,nums.size()-1);
// bubbleSort(nums);
heapSort(nums);
return nums;
}
// 簡單選擇排序
void selectSort(vector<int>& nums){
// 1.使用選擇排序,由於時間複雜度爲N方,測試用例通過率爲9/10.
int i,j;
int selected,temp;
for(i=0;i<nums.size()-1;i++){
selected = nums[i];
for(j=i;j<nums.size();j++){
if(selected>nums[j]){
temp = selected;
selected = nums[j];
nums[j] = temp;
}
}
nums[i] = selected;
}
}
// 直接插入排序
void insertSort(vector<int>& nums){
// 2.使用直接插入排序,也是由於時間複雜度爲N方,測試用例通過了9/10
int i,j,k;
int temp;
for(i=1;i<nums.size();i++){
for(j=i-1;j>=0;j--){ // 爲元素a[i],在前面找到合適的插人位置(j的後面)
if(nums[j]<nums[i]){
break;
}
}
if(j != i-1){
// 將比a[i]大的數向後移
temp = nums[i];
for(k=i-1;k>j;k--){
nums[k+1] = nums[k];
}
nums[j+1] = temp; //將a[i]放到j的後面。
}
}
}
// 快速排序
void quickSort(vector<int>& nums,int l,int h){
if(l < h){
int pivot = nums[l];
int i = l,j = h;
while(i < j){
// 從後向前找比pivot小的數。
while(i<j && nums[j]>pivot){
j--;
}
if(i<j)
nums[i++] = nums[j];
// 從前往後找比pivot大的數。
while(i<j && nums[i]<pivot){
i++;
}
if(i<j)
nums[j--] = nums[i];
}
// 最後將pivot的值放到分割點上
nums[i] = pivot;
// 分治遞歸排序
quickSort(nums,l,i-1);
quickSort(nums,j+1,h);
}
}
// 冒泡排序
void bubbleSort(vector<int>& nums){
// 時間複雜度同樣爲N方,只有9/10的用例通過
for(int i=0;i<nums.size()-1;i++){ // 比較的趟數
for(int j=0;j<nums.size()-i-1;j++){ // 每一趟中比較的次數
if(nums[j]>nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
}
// 堆排序
void heapSort(vector<int>& nums){
// 時間複雜度與快速排序相同,測試用例都可以通過
int len = nums.size();
heapBuild(nums,len);
for(int newLen=len-1;newLen>0;newLen--){
swap(nums,newLen,0);
// heapBuild(nums,newLen);
heapAdjust(nums,0,newLen);
}
}
// 建立大頂堆
void heapBuild(vector<int>& nums,int len){
for(int i=len/2-1;i>=0;i--){ // 從最後一個非葉結點開始調整
heapAdjust(nums,i,len);
}
}
// 調整大頂堆
void heapAdjust(vector<int>& nums,int i,int end){
int ded = i;
int son = 2*i + 1;
int largest = ded;
if(son < end && nums[largest] < nums[son])
largest = son;
if(son+1 < end && nums[largest] < nums[son+1])
largest = son + 1;
if(largest != i){
swap(nums,largest,i);
heapAdjust(nums,largest,end);
}
}
// 交換兩個位置上的值
void swap(vector<int>& nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
};
關於堆排序:其思想是使用數據結構中的堆來實現。
算法描述描述 :
- 將待排序的關鍵字序列{R1,R2,R3,…Rn}構建爲一個大頂堆,此時R1爲最大值。
- 將R1與最後一個元素交換位置,{R1,R2,R3…Rn-1}是一個無序序列,此時{R1,R2,R3…Rn-1} {Rn}
- 這個時候R1違反了大頂堆的定義,要對R1進行調整,讓{R1,R2,R3…Rn-1}構成大頂堆,將R1與Rn-1交換位置,此時無序序列{R1,R2,R3…Rn-2}有序序列{Rn-1,Rn}
- 重複此過程,當有序序列中有n-1個元素時,排序完成。