对于这个作业,我应该创建一个带有插入函数、删除函数和反向函数的链表。它使用输入文件获取列表的值,并使用另一个输入文件来删除值。我的插入和反向函数有效,但是当我尝试将前一个节点链接到 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
声明移近使用位置。