链接列表添加,删除和打印imlementation

时间:2016-10-29 13:52:01

标签: c++ list linked-list

下面的代码正确插入节点但是 我有一个问题,当试图打印列表时,程序不幸停止工作。 错误消息是:您的项目已停止工作。 这是我的代码:

#include <iostream>
#include <string>
using namespace std;
typedef struct st {
    string data;
    int ISBN;
    string Title;
    string Author;
    int publishedyear;
    bool borrow;
    st* next;
} NODE;

NODE* add(NODE* head, int isbn)
{
    NODE *p1, *p2;
    NODE* n;
    n = new NODE;
    n->ISBN = isbn;
    if (head == NULL) {
        head = n;
        return head;
    }
    if (n->ISBN < head->ISBN) {
        n->next = head;
        head = n;
        return head;
    }
    p1 = p2 = head;
    while (p2 != NULL) {
        if (n->ISBN < p2->ISBN) {
            n->next = p2;
            p1->next = n;
            return head;
        }
        else {
            p1 = p2;
            p2 = p2->next;
        }
    }
    n->next = p2;
    p1->next = n;
    return head;
}

void print(NODE* head)
{
    NODE* p;
    p = head;
    if (head == NULL) {
        cout << "empty list" << endl;
    }

    while (p != NULL) {
        cout << "Book ISBN Is : " << p->ISBN << endl;
        p = p->next;
    }
}
void main()
{

    // cout << "hi";
    NODE* head;
    head = NULL;
    string op;
    int isbn;
    cout << "Enter the opertion in the following format : op , ISBN" << endl;
    while (1) {
        cin >> op;
        if (op == "add") {
            cin >> isbn;
            if (op == "add") {
                head = add(head, isbn);
                cout << "book with thie ISBN code " << isbn << " is added successfuly."
                     << endl;
            }
        }
        else if (op == "print") {
            print(head);
        }
        else {
            cout << "Enter vaild operation! ." << endl;
        }
    }
}

有什么建议吗?

2 个答案:

答案 0 :(得分:3)

答案被指出,但是...我对你的代码状态感到非常不满意,所以请允许我给你一些提示。

注意:除非重点是构建列表,否则请重用现有的标准容器(特别是vector)和算法(sort),而不是构建自己的容器。

让我们从基础开始,到2016年你应该可以访问C ++ 11了。

C ++ 11允许在声明点直接初始化数据成员,我建议你为所有内置类型(积分,布尔值,浮点和指针)执行此操作,因为默认情况下它们包含垃圾这令人费解。

struct Node {
    std::string data;
    int ISBN = 0;
    std::string title;
    std::string author;
    int publishedyear = 0;
    bool borrow = false;
    Node* next = nullptr;
};

请注意,仅此一项就可以解决您的错误。它也避免了下次忘记它。

其次,add方法不应该负责创建节点。这是混合问题,它也会使节点的大部分都具有默认值,并且无法通过其ISBN来查找它。

add方法还没有考虑到这一点:如果ISBN已经在列表中该怎么办?

// Adds the new node to the list, maintaining the ordering by ISBN.
//
// Returns the new head of the list, unless an existing node in the list already
// has this ISBN in which case returns `nullptr`.
Node* add(Node* head, Node* node) {
    assert(node != nullptr && "Null argument provided");

    if (head == nullptr) {
        return node;
    }

    if (node->ISBN < head->ISBN) {
        node->next = head;
        return node;
    }

    if (node->ISBN == head->ISBN) {
        return nullptr;
    }

    //  Find "current" such that "current->ISBN" < "node->ISBN" and
    //                           "node->ISBN" <= "current->next->ISBN"
    Node* current = head;
    while (current->next != nullptr && node->ISBN > current->next->ISBN) {
        current = current->next;
    }

    if (node->ISBN == current->next->ISBN) {
        return nullptr;
    }

    node->next = current->next;
    current->next = node;

    return head;
}

注意:assert需要#include <cassert>

你的打印方法已经很好了,恭喜!

只有两个挑剔:

  • 如果您知道不会再执行任何操作,请立即返回,不要等待
  • 不要使用endl,它会附加一行结束并立即刷新缓冲区,这会导致性能问题,而不是
//  Prints the list, in order.
void print(Node* head) {
    if (head == nullptr) {
        std::cout << "empty list\n";
        return;
    }

    for (Node* p = head; p != nullptr; p = p->next) {
        std::cout << "Book ISBN: " << p->ISBN << "\n";
    }
}

最后,修改后的main

请注意,我稍微扩展了帮助文本,并提供了(干净的)quit操作。

然而,主要的变化是没有输入错误的处理。处理输出错误留给读者一个练习(提示:让他们扔掉)。

正确处理分配的内存也是一个很好的练习。

int main() {
    std::cout << "Enter one of the following operations when prompted:\n"
                 " - add <isbn>\n"
                 " - print\n"
                 " - quit\n";

    Node* head = nullptr;

    while (1) {
        std::cout << "> ";

        std::string op;
        if (!(std::cin >> op)) {
            std::cerr << "An error occurred reading the operation, sorry\n";
            break;
        }

        if (op == "quit") {
            std::cout << "See you later!\n";
            break;
        }

        if (op == "print") {
            print(head);
            continue;
        }

        if (op == "add") {
            int isbn = 0;
            if (!(std::cin >> isbn)) {
                std::cout << "Please provide a correct ISBN!\n";
                continue;
            }

            Node* node = new Node();
            node->ISBN = isbn;

            Node* h = add(head, node);
            if (h == nullptr) {
                std::cout << "This ISBN was already provided!\n";
                delete node;
                continue;
            }

            head = h;
            continue;
        }

        std::cout << "Please enter a valid operation!\n";
    }

    // Deal with allocated memory ;)
}

答案 1 :(得分:1)

let rec twoTwo (s : string) (n : int) : string = match n with |0 -> 0 // Error on this line: this expression was expected to have type string, but here has type int |_ -> s + (twoTwo s (n-1)) 永远不会设置为st::next。这使NULL中的p!=NULL测试有些问题。

解决方案:当节点是尾节点时为NULL print