小范围排序练习题

2017-06-19  本文已影响208人  郑明明
题目

已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。
给定一个int数组A,同时给定A的大小n和题意中的k,请返回排序后的数组。

思路

在所有的排序中,与位置有关的排序是插入排序和堆排序,根据题中所描述,移动的位置不超过K,那么插入排序能达到O(n *** k),堆排序可以达到O(logk * n),最后选择使用大小为k的小顶堆来不断进行处理

答案
void swapInt(int i, int j, int *A) {
    int temp = A[i];
    A[i] = A[j];
    A[j] = temp;
}

void adjustMinHeap(int *B, int start, int end) {
    for (int current = start, left = current * 2 + 1; left <= end; current = left, left = left * 2 + 1) {
        // 获取左右节点中最小的
        if (left < end && B[left] > B[left + 1]) {
            left++;
        }
        
        if (B[current] > B[left]) {
            swapInt(current, left, B);
        } else {
            break;
        }
    }
}

vector<int> sortElement(vector<int> A, int n, int k) {
    // 新建一个辅助排序的数组
    int *B = new int[k];
    for (int i = 0; i < k; i++) {
        B[i] = A[i];
    }
    
    // 构造最小堆
    for (int i = k/2 - 1; i >= 0; i--) {
        adjustMinHeap(B, i, k - 1);
    }
    
    // 中间阶段
    for (int i = k; i < n; i++) {
        A[i - k] = B[0];
        B[0] = A[i];
        adjustMinHeap(B, 0, k - 1);
    }
    
    // 最后阶段
    for (int i = n - k; i < n; i++) {
        A[i] = B[0];
        k--;
        B[0] = B[k];
        adjustMinHeap(B, 0, k);
    }
    return A;
}

上一篇 下一篇

猜你喜欢

热点阅读