簡體   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