择一个合适的排序算法针对这个数据进行排序。
给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。
测试样例:
[2,1,4,3,6,5,8,7,10,9],10,2
返回:[1,2,3,4,5,6,7,8,9,10]
思路:小根堆
class ScaleSort {
public:
vector<int> sortElement(vector<int> A, int n, int k) {
if(A.size()==0 || n<1 || k<0|| k>n){// 边界检测
return A;
}
//初始化k个数的小根堆
vector<int> minHeap(k);
for(int i=0;i<k;i++){
minHeap[i] = A[i];
}
for(int i=k/2;i>=0;i--){ //建立小根堆,堆顶元素为数组最小值
adjustHeap(minHeap,i,k);
}
for(int i=0;i<n-k;i++){//使用小根堆排序,求出前n-k个值
A[i] = minHeap[0];//将堆顶赋给A[i],换出的根结点元素,依次从小到大放到A[i]
minHeap[0] = A[i+k]; //A[i+k]赋到堆顶,从新排序
adjustHeap(minHeap,0,k);
}
for(int i=n-k;i<n;i++){//对剩余的k个值,使用堆排序
A[i] = minHeap[0];
swap(minHeap[0],minHeap[k-1]);
adjustHeap(minHeap,0,--k);//必须是--k,在减少了一个元素的序列中,调整小根堆的过程
}
return A;
}
//保持堆的性质
void adjustHeap(vector<int> &A,int parent,int n){ //小根堆
if(parent>n){
return;
}
int value = A[parent];//parent为子树的根,value记录子树根的值
int child = 2*parent+1;//child是parent的左孩子
while(child<n){ //沿较小值孩子结点向下筛选
//记录孩子值较小者,若右孩子较小,则child指向右孩子
if(child+1<n && A[child+1]<A[child]){
child++;
}
if(value<=A[child]){
break;//调整结束
}
A[parent] = A[child];//将A[child]调整到双亲结点的位置上
parent = child;//修改parent和child的值,以便继续向下调整
child = 2*parent+1;
}
A[parent] = value;//将调整结点的值放入最终位置
}
};
。。。
vector<int> sortElement(vector<int> A, int n, int k) {
sort(A.begin(), A.end());
return A;
}