繁体   English   中英

用C ++编写具有最大堆结构的优先级队列

[英]Writing a priority queue with a max heap structure in c++

我正在编写一个具有最大堆结构的优先级队列,作为学校的作业。 我可以将其写为数组,也可以使用向量。 我选择了一个向量。 因此,分配就是这样,用户从菜单中选择要添加,打印或查看元素的选项。 当用户选择添加时,他会询问要添加的人,讲师,学生或TA。 他可以输入i,I,t,T,S,s。 具有最高优先级的讲师,如果用户选择打印选项,并且队列中有一个讲师,他将首先进入。 具有第二高优先级的TA,如果队列中有TA和学生,则TA排在第一位。 如果教师人数多于一个,则该队列充当普通队列。 我已经写了大部分,或者尝试过。 我从我的教科书中获得了我的最大堆实现,因为它们提供了一个。 现在的问题是,当我在优先级队列中有多个项目并且选择打印时,它崩溃并给我一个向量下标超出范围的异常。 我一直在试图解决它,没有运气。 另外,当我尝试打印队列中的元素或打印它们时,需要用人名说出job#。 有人可以帮我找到实现该目标的方法吗?

#pragma once
#include <vector>

struct Heap
{
    std::vector<int> m_elements;

    void ReHeapDown(int, int);
    void ReHeapUp(int, int);
    void Swap(int& a, int& b);
};

    #include "heap.h"

void Heap::ReHeapDown(int index, int bottom)
{
    int maxChild, rightChild, leftChild;

    leftChild = index * 2 + 1;
    rightChild = index * 2 + 2;

    if (leftChild <= bottom)
    {
        if (leftChild == bottom)
            maxChild = leftChild;
        else
        {
            if (m_elements[leftChild] <= m_elements[rightChild])
                maxChild = rightChild;
            else
                maxChild = leftChild;
        }
        if (m_elements[index] < m_elements[maxChild])
        {
            Swap(m_elements[index], m_elements[maxChild]);
            ReHeapDown(maxChild, bottom);
        }
    }
}

void Heap::ReHeapUp(int index, int bottom)
{
    int  parent;

    if (bottom  > index)
    {
        parent = (bottom - 1) / 2;
        if (m_elements[parent]  <  m_elements[bottom])
        {
            Swap(m_elements[parent], m_elements[bottom]);
            ReHeapUp(index, parent);
        }
    }
}

void Heap::Swap(int& a, int& b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

    #include <iostream>
#include "heap.h"
#pragma once

class PQTYPE
{

private:
    Heap m_Items;

public:
    bool isEmpty() const;
    void Enqueue(int, std::string);
    void Dequeue(int, std::string);
    void printElements();
};



#include "pqtype.h"

bool PQTYPE::isEmpty() const
{
    return m_Items.m_elements.empty();
}

void PQTYPE::Enqueue(int newItem, std::string lName)
{

    if (lName == "Student")
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
    else if (lName == "TA")
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
    else if (lName == "Instructor")
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
}

void PQTYPE::Dequeue(int item, std::string lName)
{
    if (isEmpty())
        std::cout << "No jobs to print\n";
    else
    {
        m_Items.m_elements[0] = m_Items.m_elements.back();
        std::cout << "Now printing Job#" << m_Items.m_elements[item - 1] << " " << lName.c_str() << std::endl;
        m_Items.m_elements.pop_back();
        m_Items.ReHeapDown(0, item - 1);
    }
}

void PQTYPE::printElements()
{
    if (isEmpty())
        std::cout << "No jobs to print\n";
    else
    {
        for (int i = 0; i < m_Items.m_elements.size(); i++)
        {
            std::cout << "Job#" << m_Items.m_elements[i] << std::endl;
        }
    }
}


#include"pqtype.h"

struct Person
{
    int m_priority;
    std::string m_name;

    Person()
    {
        m_priority = 0;
        m_name = " ";
    }
};

int showMenu();
void addJobs(PQTYPE&, Person&);
void printJobs(PQTYPE&, Person&);
void viewJobs(PQTYPE&);

int main()
{

    int option;
    Person p;
    PQTYPE pq;

    do
    {
        option = showMenu();

        switch (option)
        {
        case 1: addJobs(pq, p);
        break;
        case 2: printJobs(pq, p);
        break;
        case 3: viewJobs(pq);
        break;
        case 4:
        break;
        default: std::cout << "Wrong input\n";
        break;
        }

    } while (option != 4);


    return 0;
}

int showMenu()
{
    int choice;
    std::cout << " 1.)Add Job\n";
    std::cout << " 2.)Print Job\n";
    std::cout << " 3.)View Jobs\n";
    std::cout << " 4.)Exit\n";
    std::cout << " Enter Choice: ";
    std::cin >> choice;

    return choice;
}

void addJobs(PQTYPE& pq, Person& per)
{
    char jobChoice;

    std::cout << "Who is the job for ( Instructor(i or I), TA(t or T), Student(s or S) :";
    std::cin >> jobChoice;

    if (jobChoice == 'S' || jobChoice == 's')
    {
        per.m_priority++;
        per.m_name = "Student";
        pq.Enqueue(per.m_priority, per.m_name);
    }
    else if (jobChoice == 'T' || jobChoice == 't')
    {
        per.m_priority++;
        per.m_name = "TA";
        pq.Enqueue(per.m_priority, per.m_name);
    }
    if (jobChoice == 'I' || jobChoice == 'i')
    {
        per.m_priority++;
        per.m_name = "Instructor";
        pq.Enqueue(per.m_priority, per.m_name);
    }
}

void printJobs(PQTYPE& pq, Person& p)
{
    pq.Dequeue(p.m_priority, p.m_name);
}

void viewJobs(PQTYPE& pq)
{
    pq.printElements();
}

在您的原始代码中,似乎没有以正确的方式初始化Dequeue()内部用于访问向量的索引。 假设您已将两个条目添加到列表中。 在这种情况下,main()中P.m_priority的值为2。现在,您是第一次调用printJobs()。 printJobs()调用pq.Dequeue(p.m_priority,p.m_name),因此Dequeue()获得p.m_priority作为其参数item 请记住, 项目的值为2。

m_Items.m_elements[0] = m_Items.m_elements.back();
std::cout << "Now printing Job#" << m_Items.m_elements[item - 1] << " " << lName.c_str() << std::endl;
m_Items.m_elements.pop_back();

您正在使用item-1的索引访问std :: vector。 这是第一次使用,因为列表中有两个元素。 在此调用中,列表上还有一个pop_back(),它的大小减小了一个。 下次调用printJobs()时,给定的参数item不会更改,它的值仍然为2。当您访问Itemlist时,不再有索引1,并且下标超出范围的异常将是抛出。

在原始版本中,没有为三个条目类型分配固定的优先级,因此我添加了这些优先级(请参阅addJobs())。

因此,存储此人姓名的可能解决方案如下所示:

struct Person
{
    int m_priority;
    std::string m_name;

    Person()
    {
        m_priority = 0;
        m_name = " ";
    }
};

struct Heap
{
    std::vector<Person> m_elements;

    void ReHeapDown(int, int);
    void ReHeapUp(int, int);
    void Swap(Person& a, Person& b);
};

void Heap::ReHeapDown(int index, int bottom)
{
    int maxChild, rightChild, leftChild;

    leftChild = index * 2 + 1;
    rightChild = index * 2 + 2;

    if (leftChild <= bottom)
    {
        if (leftChild == bottom)
            maxChild = leftChild;
        else
        {
            if (m_elements[leftChild].m_priority <= m_elements[rightChild].m_priority)
                maxChild = rightChild;
            else
                maxChild = leftChild;
        }
        if (m_elements[index].m_priority < m_elements[maxChild].m_priority)
        {
            Swap(m_elements[index], m_elements[maxChild]);
            ReHeapDown(maxChild, bottom);
        }
    }
}

void Heap::ReHeapUp(int index, int bottom)
{
    int  parent;

    if (bottom  > index)
    {
        parent = (bottom - 1) / 2;
        if (m_elements[parent].m_priority  <  m_elements[bottom].m_priority)
        {
            Swap(m_elements[parent], m_elements[bottom]);
            ReHeapUp(index, parent);
        }
    }
}

void Heap::Swap(Person& a, Person& b)
{
    Person temp;
    temp = a;
    a = b;
    b = temp;
}

#include <iostream>

class PQTYPE
{

private:
    Heap m_Items;

public:
    bool isEmpty() const;
    void Enqueue(Person);
    void Dequeue();
    void printElements();
};

bool PQTYPE::isEmpty() const
{
    return m_Items.m_elements.empty();
}

void PQTYPE::Enqueue(Person newItem)
{

    if (!newItem.m_name.compare("Student"))
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
    else if (!newItem.m_name.compare("TA"))
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
    else if (!newItem.m_name.compare("Instructor"))
    {
        m_Items.m_elements.push_back(newItem);
        m_Items.ReHeapUp(0, m_Items.m_elements.size() - 1);
    }
}

void PQTYPE::Dequeue()
{
    if (isEmpty())
        std::cout << "No jobs to print\n";
    else
    {
        Person front = m_Items.m_elements.front();
        std::cout << "Now printing Job#" << front.m_priority << " " << front.m_name.c_str() << std::endl;
        m_Items.m_elements.erase(m_Items.m_elements.begin());
        m_Items.ReHeapDown(0, m_Items.m_elements.size() - 1);
    }
}


void PQTYPE::printElements()
{
    if (isEmpty())
        std::cout << "No jobs to print\n";
    else
    {
        for (int i = 0; i < m_Items.m_elements.size(); i++)
        {
            std::cout << "Job#" << m_Items.m_elements[i].m_priority << " " << m_Items.m_elements[i].m_name.c_str() << std::endl;
        }
    }
}

int showMenu();
void addJobs(PQTYPE&, Person&);
void printJobs(PQTYPE&, Person&);
void viewJobs(PQTYPE&);

int showMenu()
{
    int choice;
    std::cout << " 1.)Add Job\n";
    std::cout << " 2.)Print Job\n";
    std::cout << " 3.)View Jobs\n";
    std::cout << " 4.)Exit\n";
    std::cout << " Enter Choice: ";
    std::cin >> choice;

    return choice;
}

void addJobs(PQTYPE& pq, Person& per)
{
    char jobChoice;

    std::cout << "Who is the job for ( Instructor(i or I), TA(t or T), Student(s or S) :";
    std::cin >> jobChoice;

    if (jobChoice == 'S' || jobChoice == 's')
    {
        per.m_priority = 0;
        per.m_name = "Student";
        pq.Enqueue(per);
    }
    else if (jobChoice == 'T' || jobChoice == 't')
    {
        per.m_priority = 1;
        per.m_name = "TA";
        pq.Enqueue(per);
    }
    if (jobChoice == 'I' || jobChoice == 'i')
    {
        per.m_priority = 2;
        per.m_name = "Instructor";
        pq.Enqueue(per);
    }
}

void printJobs(PQTYPE& pq)
{
    pq.Dequeue();
}

void viewJobs(PQTYPE& pq)
{
    pq.printElements();
}

int main()
int option;
    Person p;
    PQTYPE pq;

    do
    {
        option = showMenu();

        switch (option)
        {
        case 1: addJobs(pq, p);
        break;
        case 2: printJobs(pq);
        break;
        case 3: viewJobs(pq);
        break;
        case 4:
        break;
        default: std::cout << "Wrong input\n";
        break;
        }

    } while (option != 4);

    return 0
}

您确定ReHeapUp和ReHeapDown方法满足您的要求吗? 并且工作编号和优先级之间是否应该没有区别?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM