C - 如何使用带有仲裁器的二进制堆实现优先级队列?

时间:2018-01-27 15:38:58

标签: c queue heap

我必须使用C中的二进制堆为大学分配实现优先级队列。程序应该从输入中获取n个值,当值为0时,它应该打印ID号(因此,如果作为第5个元素添加的任务具有最高优先级7,则打印" 5")并删除队列中的最高优先级任务,当值> 0时,它应该添加新节点。为了实现ID和优先级,我使用了结构数组。

如果元素的优先级相同,那么任务也很简单,如果不是它也应该打印较低的ID ... 我已经完成了我的研究,但我设法找到的唯一建议是修改典型堆函数的片段(insertkey,heapify)以查找元素' ID。我试图这样做,但我不知道出了什么问题 - 元素仍然没有按照我希望的方式排序。我会很感激任何建议和提示!

代码:

#include <stdio.h>

#define SIZE 99999

int heapsize = 0;
int count = 0;

struct pqueue
{
    int priority;
    int id;
};

struct pqueue A[SIZE];


void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}


void initializearray()
{
    for(int i=0; i<SIZE; i++)
    {
        A[i].priority = 0;
        A[i].id = 0;
    }
}

void printheap(); //prototype of debugging function



int left(int i)
{
    return (i * 2) + 1;
}



int right(int i)
{
    return (i * 2) + 2;
}

int parent(int i)
{
    return ((i - 1) / 2);
}


void insertkey(int z)
{
    heapsize++;
    int i = heapsize - 1;
    A[i].priority = z;
    count++;
    A[i].id = count;

    while (i != 0 && A[parent(i)].priority < A[i].priority)
    {
        swap(&A[i].priority, &A[parent(i)].priority);
        swap(&A[i].id, &A[parent(i)].id);
        i = parent(i);
    }


    i = heapsize-1;
    while(i != 0 && A[parent(i)].priority == A[i].priority && A[parent(i)].id > A[i].id )
        {
        swap(&A[i].priority, &A[parent(i)].priority);
        swap(&A[i].id, &A[parent(i)].id);
        i = parent(i);
        }

     //   printheap();
}



void maxheapify(int i)
{
    int l = left(i);
    int r = right(i);
    int largest;

    if (l <= heapsize && A[l].priority >= A[i].priority)
    {
        largest = l;

        if(A[l].priority == A[i].priority)
        {
            if(A[l].id < A[i].id)
            {
                largest = l;
            }

            else
            {
                largest = i;
            }
        }

    }

    else
    {
        largest = i;
    }

    if (r <= heapsize && A[r].priority >= A[largest].priority)
    {
        largest = r;

        if(A[r].priority == A[largest].priority)
        {
            if(A[r].id < A[largest].id)
            {
                largest = r;
            }
        }
    }

    if (largest != i)
    {
        swap(&A[i].priority, &A[largest].priority);
        swap(&A[i].id, &A[largest].id);
        maxheapify(largest);
    }
}

int extractmax()
{
    int max = A[0].id;
    A[0].priority = A[heapsize-1].priority;
    A[0].id = A[heapsize-1].id;
    heapsize--;
    //printheap();
    maxheapify(0);
    return max;
}

void printheap() // debug function
{
    for(int i = 0; i < heapsize; i++)
    {
        printf("prio %d id %d \n", A[i].priority, A[i].id);
    }
}


int main()
{
    int n;
    int z;

    initializearray();
    scanf("%d", &n);

    for(int i=0; i<n; i++)
    {
        scanf("%d", &z);

        if(z != 0)
        {
            insertkey(z);
        }

        else
        {
            int local = extractmax();

            if(local != 0 && heapsize+1 != 0)
            {
                printf("%d\n", local);
                // printheap();
            }
        }
    }

    return 0;
}

示例输入:

  

7

     

3 0 0 2 8 8 0

输出:

  

1

     

3

示例输入(问题在于:)

  

10

     

1 1 1 1 2 0 0 0 0 0

输出:

  

5

     

3

     

2

     

4

     

1

预期产出:

  

5

     

1

     

2

     

3

     

4

感谢您的时间!

1 个答案:

答案 0 :(得分:4)

如果优先级相同,则编写一个考虑id的比较函数,而不是将逻辑直接合并到堆实现中:

int pqless(const struct pqueue *a, const struct pqueue *b)
{
    if (a->priority < b->priority) return 1;
    if (a->priority > b->priority) return 0;

    return (a->id > b->id);
}

如果a的优先级低于b,则此函数返回true。如果两个优先级相等,则如果a的id小于b,则返回true。

现在更新堆代码。无论您在哪里比较原始代码中的优先级,现在只需调用函数:

void insertkey(int z)
{
    int i = heapsize++;

    A[i].priority = z;
    A[i].id = ++count;

    while (i != 0 && pqless(&A[parent(i)], &A[i])) {
        swap(&A[i].priority, &A[parent(i)].priority);
        swap(&A[i].id, &A[parent(i)].id);
        i = parent(i);
    }
}

void maxheapify(int i)
{
    int l = left(i);
    int r = right(i);
    int largest = i;

    if (l <= heapsize && !pqless(&A[l], &A[i])) largest = l;
    if (r <= heapsize && !pqless(&A[r], &A[largest]))largest = r;

    if (largest != i) {
        swap(&A[i].priority, &A[largest].priority);
        swap(&A[i].id, &A[largest].id);
        maxheapify(largest);
    }
}