尝试将上一个节点链接到要删除的节点之后的节点时出错

Error while trying link previous node to the node after the node to be deleted

本文关键字:节点 删除 之后 出错 上一个 链接      更新时间:2023-10-16

对于这个作业,我应该创建一个带有插入函数、删除函数和反向函数的链表。它使用输入文件获取列表的值,并使用另一个输入文件来删除值。我的插入和反向函数有效,但是当我尝试将前一个节点链接到 nodeptr 之后的节点时,我的删除函数在 else 语句中给我一个错误。它说使用了可能未初始化的本地指针变量"previousNodePtr"。我不确定我做错了什么来重新链接我的列表,以便我可以删除所需的节点。您可以在删除功能中找到我的问题大约 90 行。这是我的代码:

//use a linked list to maintain a sorted list of numbers in descending
//order
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
const int ARRAY_SIZE = 100;
//input the data from a file to an array A, n is used to calculate the total number of
//data in the file
void input(int A[], int & n, const string & fileName) 
{
    ifstream inputFile;
    int value;
    inputFile.open(fileName.c_str());
    if (!inputFile)
    {
        cout << "Error opening the file " << fileName << endl;
        exit(0);
    }
    //read data until the end of the file and calculate n
    while(inputFile >> value)
    {
        A[n] = value;
        n++;
    }
    inputFile.close();
}

struct ListNode
{
    int value;
    ListNode *next;
    //struct constructor
    ListNode (int input_value, ListNode * input_next = NULL)
    {
        value = input_value;
        next = input_next;
    }
};
//define a class for the linked list
class LinkedList
{
    private:
        ListNode *head;// the head of the linked list
    public:
        LinkedList() {head = NULL;}
        ~LinkedList();
        void insert(int x);// add a number x the end of the list
        void remove(int x);//remove x from the list
        void reverse();//reverse the list
        void printListToFile(const string & fileName) const; // print the     list to a file
        void printList() const; // print the list to the console (computer's screen), this function may be helpful when you test your program
};
//insert
void LinkedList::insert(int x)
{   
    ListNode *nodePtr, *previousNodePtr;
    if (head == NULL || head->value <= x)
    {
        head = new ListNode(x, head);
    }
    else
    {
        previousNodePtr = head;
        nodePtr = head->next;
        while (nodePtr != NULL && nodePtr->value > x)
        {
            previousNodePtr = nodePtr;
            nodePtr = nodePtr->next;
        }
        previousNodePtr->next = new ListNode(x, nodePtr);
    }
}
//remove
void LinkedList::remove(int x)
{
    ListNode *nodePtr, *previousNodePtr;
    if (!head) return;
    if (head->value == x)
    {
        nodePtr = head;
        head = head->next;
        delete nodePtr;
    }
    else
    {
        nodePtr = head;
        while (nodePtr != NULL && nodePtr->value != x)
        {
            previousNodePtr = nodePtr;
            nodePtr = nodePtr->next;
        }
        if (nodePtr)
        {
            previousNodePtr->next = nodePtr->next;
            delete nodePtr;
        }
    }
}
//reverse
void LinkedList::reverse()
{
    ListNode *nodePtr, *previousNodePtr, *nodeNext;
     nodePtr = head;
     nodeNext = NULL;
     previousNodePtr = NULL;
    while (nodePtr != NULL)
    {
        nodeNext = nodePtr->next;
        nodePtr->next = previousNodePtr;
        previousNodePtr = nodePtr;
        nodePtr = nodeNext;
    }
    head = previousNodePtr;
}
void LinkedList::printList() const
{
    ListNode *p = head;
    while (p != NULL)
    {
        if (p->next == NULL)
            cout << p->value << endl; 
        else
            cout << p->value << " -> ";
        p = p->next;
    }
}
void LinkedList::printListToFile(const string & fileName) const
{
    ofstream outputFile;
    outputFile.open(fileName.c_str());
    if (!outputFile)
    {
        cout << "Error opening the file " << fileName << endl;
        exit(0);
    }
    ListNode *p = head;
    while (p != NULL)
    {
        if (p->next == NULL)
            outputFile << p->value << endl; 
        else
            outputFile << p->value << " -> ";
        p = p->next;
    }
    outputFile.close();
}
//destructor, delete all nodes
LinkedList::~LinkedList()
{
    ListNode *p = head;
    while (p != NULL)
    {
        ListNode * garbageNode = p;
        p = p->next;
        delete garbageNode;
    }
}
int main()
{
    int A[ARRAY_SIZE];// store numbers for insert
    int B[ARRAY_SIZE]; // store numbers for remove
    int n = 0;// the number of elements that will be stored in A
    int m = 0;// the number of elements that will be stored in B
    string inputFile1 = "hw2_Q1_insertData.txt"; // file with data for     insert 
    string inputFile2 = "hw2_Q1_removeData.txt"; // file with data for     remove 
    //input data from the two files
    input(A, n, inputFile1); 
    input(B, m, inputFile2); 
    LinkedList list;
    //do insert operations
    for (int i = 0; i < n; i++)
        list.insert(A[i]);
    //do remove operations
    for (int i = 0; i < m; i++)
        list.remove(B[i]);
    //list.printList();
    //reverse the list
    list.reverse();
    list.printList();
    //print the list to the output file
    string outputFile = "hw2_Q1_output.txt"; // the output file 
    list.printListToFile(outputFile);
    return 0;
}

在这种情况下,编译器过于小心 - 它警告您,程序中可能存在一条路径,其中previousNodePtr未设置为值。

当您检查head与值匹配并更早返回时,您将始终至少执行一次循环,因此将始终设置previousNodePtr

解决此问题的一种方法是在声明时将previousNodePtr设置为 NULL,这将消除警告。

更好的方法是意识到您不需要在循环中再次针对head节点进行测试。然后,您可以执行以下操作:

...
else
{
    ListNode *previousNodePtr = head;
    nodePtr = head->next;
    while (nodePtr != NULL && nodePtr->value != x)
    {
        previousNodePtr = nodePtr;
        nodePtr = nodePtr->next;
    }
    if (nodePtr)
    {
        previousNodePtr->next = nodePtr->next;
        delete nodePtr;
    }

另请注意,我将previousNodePtr声明移近使用位置。