在c ++中编写具有最大堆结构的优先级队列

时间:2017-09-14 00:17:06

标签: c++ queue

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

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

1 个答案:

答案 0 :(得分:0)

在原始代码中,Dequeue()内部用于访问向量的索引似乎没有以正确的方式初始化。我们假设您已在列表中添加了两个条目。在这种情况下,main()中的P.m_priority值为2.现在您第一次调用printJobs()。 printJobs()调用pq.Dequeue(p.m_priority,p.m_name),因此Dequeue()将p.m_priority作为其参数 item 。请注意, 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方法符合您的要求吗?并且工作号和优先级之间是否应该有区别?