Несортированный двусвязный список для приоритетной очереди строк в C++

Я пытаюсь реализовать «приоритетную» очередь строк с несортированным двусвязным списком, но я полностью застрял в методе dequeue (в нижней части кода/могут возникнуть проблемы раньше). Под приоритетной очередью я подразумеваю очередь, в которой первый удаляемый из очереди элемент является минимальным элементом.

Не могли бы вы взглянуть на мой код и дать мне несколько советов, где я ошибаюсь?

Спасибо большое за вашу помощь.

Мэтт

/*************************************************************
 * File: pqueue-doublylinkedlist.cpp
 *
 * Implementation file for the DoublyLinkedListPriorityQueue
 * class.
 */

#include "pqueue-doublylinkedlist.h"
#include "error.h"

/* Implementation notes: DoublyLinkedListPriorityQueue constructor
 * ----------------------------------------------------------------
 * This function initializes an empty priority queue represented as a doubly 
 * linked-list.
 */

DoublyLinkedListPriorityQueue::DoublyLinkedListPriorityQueue() {
    listHead = new Cell;
    listHead = NULL;
    count = 0;
}

/* Implementation notes: DoublyLinkedListPriorityQueue destructor
 * --------------------------------------------------------------
 * This function deletes every cell in the priority queue.
 */

DoublyLinkedListPriorityQueue::~DoublyLinkedListPriorityQueue() {
    Cell *temp, *link;
    temp = link = new Cell;

    temp = listHead;
    while (temp != NULL) {
        link = temp->next;
        delete temp;
        temp = link;
    }
    count = 0;
}

/* Implementation notes: DoublyLinkedListPriorityQueue size
 * --------------------------------------------------------
 * Returns the size of the priority queue.
 */

int DoublyLinkedListPriorityQueue::size() {
    return count;
}

/* Implementation notes: DoublyLinkedListPriorityQueue isEmpty
 * -----------------------------------------------------------
 * Returns true if there is no cell within the list.
 */

bool DoublyLinkedListPriorityQueue::isEmpty() {
    return (count == 0);
}

/* Implementation notes: DoublyLinkedListPriorityQueue enqueue
 * -----------------------------------------------------------
 * Enqueues the new Cell into the chain just after the head Cell.
 */

void DoublyLinkedListPriorityQueue::enqueue(string value) {

    Cell *newOne = new Cell;
    newOne->str = value;
    newOne->prev = NULL;

    newOne->next = listHead;
    listHead = newOne;

    count++;
}

/* Implementation notes: DoublyLinkedListPriorityQueue peek
 * --------------------------------------------------------
 * Returns the string value of the next node to be dequeued.
 */

string DoublyLinkedListPriorityQueue::peek() {
    if (isEmpty()) error("peek an empty list");

    curr = new Cell;

    curr = listHead;
    string result = listHead->str;

    for (curr = listHead; curr != NULL; curr = curr->next) {
        if (curr->str != "" && curr->str < result) {
            result = curr->str;
        }
    }

    return result;
}

/* Implementation notes: DoublyLinkedListPriorityQueue dequeueMin
 * --------------------------------------------------------------
 * Deletes the node with the smallest string and returns this string value.
 */

string DoublyLinkedListPriorityQueue::dequeueMin() {
    if (isEmpty()) error("dequeueMin an empty list");

    Cell *temp;
    temp = curr = new Cell;
    temp = curr = NULL;

    string result = listHead->str;

    // find the node to delete and store a pointer on it
    for (curr = listHead; curr != NULL; curr = curr->next) {
        if (curr->str != "" && curr->str < result) {
            result = curr->str;
            temp = curr;
        }
    }

    // first position (if: node to delete prev == NULL)
    if (temp->prev == NULL) {
        temp = listHead->next;
        delete listHead;
        listHead = temp;

    // delete from last position (else if: node to delete next == NULL)
    } else if (temp->next == NULL) {
        curr = temp->prev;
        curr->next = NULL;
        delete temp;

    // other position (else)
    } else {
        temp->prev->next = temp->next;
        temp->next->prev = temp->prev;
        delete temp;
    }

    count--;

    return result;
}

person matt1101    schedule 02.08.2014    source источник
comment
Скорее всего, ваши шансы на участие значительно увеличатся, если вы подробно расскажете о проблеме и связанном с ней вопросе. Это очередь с приоритетом, поэтому ожидаемый вывод, скорее всего, можно сделать вывод, но что вы испытываете* и чем оно отличается? Я-думаю-что-то-не так несколько выкрикивает вопрос: Что заставляет вас так думать? (и кроме того, это упражнение или есть какая-то другая причина std::priority_queue<> нельзя использовать?)   -  person WhozCraig    schedule 02.08.2014
comment
Похоже, кто-то уже разместил полные ответы на вопрос о назначении очереди приоритетов CS106B на git-hub< /а>. Может быть, это может помочь?   -  person David C. Rankin    schedule 02.08.2014
comment
@WhozCraig: хорошая мысль! Я получаю сообщение об ошибке EXC_BAD_ACCESS при первом условии if метода dequeueMin. И да, это упражнение, целью которого является работа над различными реализациями приоритетных очередей.   -  person matt1101    schedule 02.08.2014
comment
@DavidC.Rankin: большое спасибо за ссылку. Я все еще пытаюсь решить ее, не глядя на решение... но это может помочь в ближайшем будущем ;-)   -  person matt1101    schedule 02.08.2014


Ответы (1)


Реализация очереди с приоритетами в виде двусвязного списка (или вообще ее реализация) довольно необычная, поскольку для использования доступна реализация STL:

#include <iostream>
#include <queue>
#include <functional>

int main(void) {
    std::priority_queue<std::string, std::vector<std::string>,
            std::greater<std::string> > pq;

    pq.push("foo");
    pq.push("bar");
    pq.push("quux");

    while( !pq.empty() ) {
        std::cout << pq.top() << std::endl;
        pq.pop();
    }

    return 0;
}

Я пишу это в предположении, что, возможно, вы просто не знали, что этот функционал доступен, а не там есть реальная причина, по которой вы хотите сделать свою собственную реализацию и сделать это довольно странным образом.

Если я ошибаюсь и приведенный выше указатель вам не нужен, я бы рекомендовал адаптировать вашу реализацию к интерфейсу стандартной версии (насколько это возможно) и объяснить, почему вы не хотите использовать версию STL. , так как эти шаги повысят знакомство с вашим кодом для пользователей StackOverflow (как для тех, кто может ответить на ваш вопрос лучше, чем я, так и для будущих пользователей с похожими вопросами).

person Emmet    schedule 02.08.2014
comment
Спасибо за ваше сообщение. Я должен был уточнить, что это задание Стэнфорда (CS106B), цель которого состоит в том, чтобы заставить студентов реализовать приоритетную очередь 4 различными способами. Я сделал векторную реализацию, заказал односвязный список, но застрял на двусвязном списке. Спасибо, в любом случае! - person matt1101; 02.08.2014
comment
@matt1101: В Летнем квартале работает 106B? - person Emmet; 02.08.2014
comment
Думаю, да, но я не в Стэнфорде. Я работаю над заданием от весны 2013 года, чтобы изучить программирование. Указатели - это немного сложно для меня. - person matt1101; 02.08.2014
comment
Вы правы, они проводят его летом. Я удивлен. Поначалу указатели представляют собой некоторую проблему для всех, но как только они «щелкнут», они станут второй натурой, и вы не поймете, почему у вас когда-либо были проблемы с ними. Указатель - это просто адрес памяти, где объект (в широком смысле) хранится в памяти, и размер этого объекта (так что арифметика указателя работает). Если вы выясните, как создавать, поддерживать и перемещаться по структуре с максимальной кучей, используя двусвязный список, то все готово. - person Emmet; 02.08.2014