【PAT甲级 堆排序/折半插入排序】1098 Insertion or Heap Sort (25 分)

堆排序和插入排序都使用algorithm中的函数

# include <bits/stdc++.h>
using namespace std;

vector<int> A;
vector<int> A_origin;
vector<int> seq;
int N;
bool isInsertSort = false;
bool isHeapSort = false;

bool isSameArray() {
    
    
    for(int i = 1;i <= N;++i)
        if(A[i] != seq[i])
            return false;
    return true;
}

void insertSort() {
    
    
    for(int i = 2;i <= N;++i){
    
    
        // 检查这一次的排序中途序列是否符合seq(因为最后一步就是完成排序成为有序序列的一步,所以判断这一步可以放在前面)
        isInsertSort = (isSameArray() && i != 2); // 是中间步骤与seq相同而不是初始步骤,所以排除i=2的初始情况
        
        sort(A.begin() + 1, A.begin() + i + 1); // 使用sort函数完成有序部分的排序
        
        // 输出下一趟排序
        if(isInsertSort){
    
    
            cout << "Insertion Sort\n";
            for(int k = 1;k <= N;++k)
                cout << A[k] << (k == N?"\n":" ");
            return;
        }
    }
}

void heapSort() {
    
    
    make_heap(A.begin()+1, A.end());
    for(int i = N;i > 1;--i){
    
    
        isHeapSort = (isSameArray() && i != N);  // 是中间步骤与seq相同而不是初始步骤,所以排除i=N的初始情况

        pop_heap(A.begin()+1, A.begin()+1 + i); // 这个pop_heap库函数只是将堆顶元素放到数组尾部,然后再从堆顶向下调整

        if(isHeapSort){
    
    
            cout << "Heap Sort\n";
            for(int k = 1;k <= N;++k)
                cout << A[k] << (k == N?"\n":" ");
            return;
        }
    }
}

int main() {
    
    
    cin >> N;
    A.resize(N+1);
    seq.resize(N+1);
    for(int i = 1;i <= N;++i)
        cin >> A[i];
    for(int i = 1;i <= N;++i)
        cin >> seq[i];
    A_origin = A;

    insertSort();
    A = A_origin; // 复原A
    heapSort();
    
    return 0;
}

自己写函数建堆并进行堆排序

# include <bits/stdc++.h>
using namespace std;

vector<int> A;
vector<int> A_origin;
vector<int> seq;
int N;
bool isInsertSort = false;
bool isHeapSort = false;

bool isSameArray() {
    
    
    for(int i = 1;i <= N;++i)
        if(A[i] != seq[i])
            return false;
    return true;
}

void insertSort() {
    
    
    for(int i = 2;i <= N;++i){
    
    
        // 检查这一次的排序中途序列是否符合seq(因为最后一步就是完成排序成为有序序列的一步,所以判断这一步可以放在前面)
        isInsertSort = (isSameArray() && i != 2); // 是中间步骤与seq相同而不是初始步骤,所以排除i=2的初始情况

        // 可以自己写,也可以直接用sort函数
        if(A[i] < A[i-1]){
    
     // 如果待插入元素 < 有序序列的最小元素,说明需要进行插入,否则这一步已经自然完成了插入(自然地插入到了有序序列最后)
            A[0] = A[i]; // 使用A[0]哨兵保存待插入元素
            int pos = lower_bound(A.begin(), A.begin()+i-1, A[0]) - A.begin(); // 记得减A.begin()
            for(int j = i-1;j >= pos;--j) // 将A[i]到插入位置前的元素后移以腾出插入位置并覆盖待插入元素原本的位置(待插入元素已被A[0]保存)
                A[j+1] = A[j];
            A[pos] = A[0];
        }
        // sort(A.begin() + 1, A.begin() + i + 1);
        
        // 输出下一趟排序
        if(isInsertSort){
    
    
            cout << "Insertion Sort\n";
            for(int k = 1;k <= N;++k)
                cout << A[k] << (k == N?"\n":" ");
            return;
        }
    }
}

void downAdjust(int low, int high) {
    
    
    int i = low; // 待调整节点
    int j = 2 * i; // 待调整节点的左孩子
    while(j <= high) {
    
     // 
        if(j + 1 <= high  && A[j+1] > A[j]) // 使得j指向i的值较大的孩子
            j++;
        if(A[j] > A[i]) {
    
     // 大根堆,如果孩子的值比父节点的大,那就要调整
            swap(A[i], A[j]);
            i = j;
            j = 2 * i;
        } else 
            break;
    }
}

void creatMaxHeap(){
    
    
    for(int i = N/2;i >= 1;--i) // 从最后一个非叶子结点到根节点进行向下调整以使得整个序列堆化
        downAdjust(i, N);
}

void heapSort() {
    
    
    // make_heap(A.begin()+1, A.end());
    creatMaxHeap();
    for(int i = N;i > 1;--i){
    
    
        isHeapSort = (isSameArray() && i != N);  // 是中间步骤与seq相同而不是初始步骤,所以排除i=N的初始情况

        // pop_heap(A.begin()+1, A.begin()+1 + i); // 这个pop_heap库函数只是将堆顶元素放到数组尾部,然后再从堆顶向下调整
        swap(A[1], A[i]); // 交换末尾节点和根节点(最值节点)
        downAdjust(1, i-1); // 从根节点向下调整

        if(isHeapSort){
    
    
            cout << "Heap Sort\n";
            for(int k = 1;k <= N;++k)
                cout << A[k] << (k == N?"\n":" ");
            return;
        }
    }
}


int main() {
    
    
    cin >> N;
    A.resize(N+1);
    seq.resize(N+1);
    for(int i = 1;i <= N;++i)
        cin >> A[i];
    for(int i = 1;i <= N;++i)
        cin >> seq[i];
    A_origin = A;

    insertSort();
    A = A_origin; // 复原A
    heapSort();
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/MYMarcoreus/article/details/114282732