对数组进行排序
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个元素时,排序完成。