简体   繁体   English

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

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

I am writing a priority queue with a max heap structure as an assignment for school. 我正在编写一个具有最大堆结构的优先级队列,作为学校的作业。 I can either write it as an array or I can use a vector. 我可以将其写为数组,也可以使用向量。 I chose a vector. 我选择了一个向量。 So the assignment is this, the user chooses options from a menu where he either wants to add,print, or view the elements. 因此,分配就是这样,用户从菜单中选择要添加,打印或查看元素的选项。 When the user chooses to add he gets ask who wants to be added, the instructor, student, or TA. 当用户选择添加时,他会询问要添加的人,讲师,学生或TA。 He can enter i,I,t,T,S,s. 他可以输入i,I,t,T,S,s。 The instructor having the highest priority where if the user chooses the option to print and there is an instructor in the queue he gets to go first. 具有最高优先级的讲师,如果用户选择打印选项,并且队列中有一个讲师,他将首先进入。 The TA having the second highest priority where if there is a TA and a student in the queue, the TA goes first. 具有第二高优先级的TA,如果队列中有TA和学生,则TA排在第一位。 If there is is more than one instructor than the queue acts as a normal queue. 如果教师人数多于一个,则该队列充当普通队列。 I have written most of it, or tried. 我已经写了大部分,或者尝试过。 I got my max heap implementation from my textbook since they provide one. 我从我的教科书中获得了我的最大堆实现,因为它们提供了一个。 Now the problem is this, when I have more than one item in the priority queue and I choose to print, it crashes and gives me a vector subscript out of range exception. 现在的问题是,当我在优先级队列中有多个项目并且选择打印时,它崩溃并给我一个向量下标超出范围的异常。 I been trying to fix it and no luck. 我一直在试图解决它,没有运气。 Also, when I try to print the elements in the queue or print them, it needs to say the job# with the name of the person. 另外,当我尝试打印队列中的元素或打印它们时,需要用人名说出job#。 Can someone help me find a way to implement that. 有人可以帮我找到实现该目标的方法吗?

#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();
}

In your original code the index used inside Dequeue() for accessing the vector doesn't seem to be initialised in the right way. 在您的原始代码中,似乎没有以正确的方式初始化Dequeue()内部用于访问向量的索引。 Let's assume that you have added two entries to your list. 假设您已将两个条目添加到列表中。 In this case the value of P.m_priority inside your main() is 2. Now you're calling printJobs() for the first time. 在这种情况下,main()中P.m_priority的值为2。现在,您是第一次调用printJobs()。 printJobs() calls pq.Dequeue(p.m_priority, p.m_name), so Dequeue() gets p.m_priority as its parameter item . printJobs()调用pq.Dequeue(p.m_priority,p.m_name),因此Dequeue()获得p.m_priority作为其参数item Keep in mind that item has the value 2. 请记住, 项目的值为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();

You're accessing your std::vector using an index of item - 1 . 您正在使用item-1的索引访问std :: vector。 This works for the first time, as there are two elements in your list. 这是第一次使用,因为列表中有两个元素。 In this call, there is also a pop_back() done on your list, which decreases its size by one. 在此调用中,列表上还有一个pop_back(),它的大小减小了一个。 The next time you call printJobs(), the given parameter item won't have changed, it still has the value 2. When you access your Itemlist, there is no longer an index of 1, and an subscript out of range exception will be thrown. 下次调用printJobs()时,给定的参数item不会更改,它的值仍然为2。当您访问Itemlist时,不再有索引1,并且下标超出范围的异常将是抛出。

There were no fixed priorities assigned to the three entry types in your original version, so I added these (see addJobs() ). 在原始版本中,没有为三个条目类型分配固定的优先级,因此我添加了这些优先级(请参阅addJobs())。

So a possible solution to store the person's name could look like this: 因此,存储此人姓名的可能解决方案如下所示:

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
}

Are you sure that the methods ReHeapUp and ReHeapDown meet your requirements? 您确定ReHeapUp和ReHeapDown方法满足您的要求吗? And shouldn't there be a distinction between job number and priority? 并且工作编号和优先级之间是否应该没有区别?

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

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