已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。
给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。
可采用的方法:1. 插入排序
2. 堆排序
本文中采用方法2实现:
1)建立一个大小为k的小根堆,并取堆顶元素保存到原数组中。
2)依次加入数组中的后一个元素并对堆结构进行调整,始终维持大小为k的小根堆。
3)采用普通堆排序的方法将最后k个元素排序并保存到原数组中。
class ScaleSort {
public:
vector<int> sortElement(vector<int> A, int n, int k) {
int heap[k];
//建立大小为k的数组维护大小为k的小根堆
for(int i=0; i<k; i++)
heap[i] = A[i];
for(int i=k/2-1; i>=0; i--) //建立初始堆
heapAdjust(heap, i, k);
for(int i = k; i<n; i++) //将堆顶元素赋给A,维护大小为k的堆
{
A[i-k] = heap[0];
heap[0] = A[i];
heapAdjust(heap, 0, k);
}
//后k个元素采用正常堆排序的方式得到并赋给A
for(int i = n-k; i<n; i++)
{
A[i] = heap[0];
swap(heap[0], heap[k-1]);
heapAdjust(heap, 0, --k);
}
return A;
}
void heapAdjust(int* heap, int p, int n)
{
int cur = heap[p];
while(p*2+1<n)
{
int child = p*2+1;
if(child+1<n && heap[child]>heap[child+1]) child++;
if(heap[child]<cur)
{
heap[p] = heap[child];
p = child;
}
else break;
}
heap[p] = cur;
}
};