1. 程式人生 > 其它 >MOOC資料結構PTA05-樹7 堆中的路徑

MOOC資料結構PTA05-樹7 堆中的路徑

題目

將一系列給定數字插入一個初始為空的小頂堆H[]。隨後對任意給定的下標i,列印從H[i]到根結點的路徑。

輸入格式:

每組測試第1行包含2個正整數N和M(≤1000),分別是插入元素的個數、以及需要列印的路徑條數。下一行給出區間[-10000, 10000]內的N個要被插入一個初始為空的小頂堆的整數。最後一行給出M個下標。

輸出格式:

對輸入中給出的每個下標i,在一行中輸出從H[i]到根結點的路徑上的資料。數字間以1個空格分隔,行末不得有多餘空格。

輸入樣例:

5 3
46 23 26 24 10
5 4 3
結尾無空行

輸出樣例:

24 23 10
46 23 10
26 10
結尾無空行

題目解析

題目的意思是按照輸入順序輸入,並同時建立最小堆,再遍歷即可。
然而一開始我想先輸入陣列,自然形成一個堆,再對其從最後一個父節點開始遍歷調整堆頂的數,(想著能降低時間複雜度),但問題是這樣出來的陣列,葉節點與輸入順序不同,遂放棄。

程式碼

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define Maximum 1000
typedef struct hnode {
    /*堆陣列*/
    int* data;
    /*當前個數*/
    int size;
    /*最大容量*/
    int capacity;
} Hnode, *Heap;

/*函式宣告*/
Heap initHeap(int max);
bool isFull(Heap H);
bool isEmpty(Heap H);
bool insert(Heap H, int x);
int delete (Heap H);
void PercDown(Heap H, int p);
void buildMinHeap(Heap H);
void printPath(Heap H, int M);

/*主函式*/
int main() {
    int N, M;
    scanf("%d%d", &N, &M);
    int tempData;
    Heap H = initHeap(Maximum);
    for (int i = 1; i <= N; i++) {
        
        /*scanf("%d", &H->data[i]);
        H->size++;*/

        scanf("%d", &tempData);
        insert(H, tempData);
    }
    /*此種方式會導致葉節點順序與輸入順序不同步*/
    //buildMinHeap(H);
    printPath(H, M);

    return 0;
}

/*函式定義*/
Heap initHeap(int max) {
    Heap H = (Heap)malloc(sizeof(Hnode));
    H->data = (int*)malloc((Maximum + 1) * sizeof(int));
    /*最小堆的哨兵*/
    H->data[0] = -10001;
    H->size = 0;
    H->capacity = Maximum;
    return H;
}
bool isFull(Heap H) {
    return (H->size == H->capacity);
}
bool isEmpty(Heap H) {
    return (H->size == 0);
}
bool insert(Heap H, int x) {
    if (isFull(H))
        return false;
    Heap temp;
    int seat = ++H->size;
    /*如果待插入位置的父親大於待插入元素,將父親下放*/
    while (x < H->data[seat / 2]) {
        H->data[seat] = H->data[seat / 2];
        seat = seat / 2;
    }
    H->data[seat] = x;
    return true;
}
int delete (Heap H) {
    if (isEmpty(H))
        return false;
    int seat, parent, child;
    int MaxItem = H->data[1];
    /* 用最大堆中最後一個元素從根結點開始向下過濾下層結點 */
    int x = H->data[H->size--]; /* 注意當前堆的規模要減小 */
    for (parent = 1; parent * 2 <= H->size; parent = child) {
        child = parent * 2;
        if (child != H->size) /* Child指向左右子結點的較小者 */
            child = (H->data[child] < H->data[child + 1]) ? child : child + 1;
        if (x <= H->data[child])
            break; /* 找到了合適位置 */
        else /* 向下濾X,把上層的根用child填充,即把小的child往上放 */
            H->data[parent] = H->data[child];
    }
    H->data[parent] = x;
    return MaxItem;
}
void PercDown(Heap H, int p) {
    /* 下濾:將H中以H->Data[p]為根的子堆調整為最xiao堆 */
    int Parent, Child;
    int X;

    X = H->data[p]; /* 取出根結點存放的值 */
    for (Parent = p; Parent * 2 <= H->size; Parent = Child) {
        Child = Parent * 2;
        if ((Child != H->size) && (H->data[Child] > H->data[Child + 1]))
            Child++; /* Child指向左右子結點的較xiao者 */
        if (X <= H->data[Child])
            break; /* 找到了合適位置 */
        else       /* 下濾X */
            H->data[Parent] = H->data[Child];
    }
    H->data[Parent] = X;
}
void buildMinHeap(Heap H) {
    /* 調整H->Data[]中的元素,使滿足最大堆的有序性  */
    /* 這裡假設所有H->Size個元素已經存在H->Data[]中 */

    int i;

    /* 從最後一個結點的父節點開始,到根結點1 */
    for (i = H->size / 2; i > 0; i--)
        PercDown(H, i);
}
void printPath(Heap H, int M) {
    int* index = (int*)malloc(M * sizeof(int));
    int temp;
    for (int i = 0; i < M; i++)
        scanf("%d", index + i);
    /*輸出序列*/
    for (int i = 0; i < M; i++) {
        temp = index[i];
        while (temp > 1) {
            printf("%d ", H->data[temp]);
            temp /= 2;
        }
        if (i != M - 1)
            printf("%d\n", H->data[1]);
        else
            printf("%d", H->data[1]);
    }
}