【问题标题】:Deleting a node in a doubly linked list删除双向链表中的节点
【发布时间】:2026-02-20 23:55:02
【问题描述】:

我试图从具有从文件中读取的数据的双向链表中删除一个节点,并将其重写到具有未删除节点的文件中。但我做错了。

要么只删除节点的一​​部分,要么不删除任何东西(起始节点)。

这是我的标题

hw07.h

#ifndef HW07_H_
#define HW07_H_

#include <iostream>
#include <fstream>
using namespace std;

typedef struct slist  slist;

struct stud
{
    string term;
    string title;
    string description;
    string tktNum;
    string location;
    string lecDay;
    string instructor;
    string labLoc;
    string labDay;
    string labInstruct;
    string units;
    string preReqs;
    string grade;
};
struct sentry
{
    slist *list;
    sentry *next;
    sentry *prev;
    stud *data;
};
struct slist
{
    int length;
    sentry *first;
    sentry *last;
};

void readFile(slist *&header);
void deleteDataTN(slist *&header);

#endif

我的主

hw07.cpp

#include "hw07.h"

int main()
{
    slist *header = NULL;

    readFile(header);
    deleteDataTN(header);
    return 0;
 }

我的 readFile 函数

readFile.cpp

#include "hw07.h"

void readFile(slist *&header)
{
    ifstream fin;
    sentry *node, *temp;

    fin.open("sbclassdb.txt");
    while(!fin.eof())
    {
        if(header == NULL)
        {
            header = new slist;
            header-> length = 0;
            header-> first = NULL;
            header-> last  = NULL;

            node = new sentry;
            header-> first = node;
            header-> last  = node;
            node-> prev = NULL;
            node-> next = NULL;
        }else
        {
            node = new sentry;
            node-> prev = header-> last;
            node-> next = NULL;
            temp = header -> last;
            temp-> next = node;
            header-> last = node;
        }
    node->data = new stud;
    getline(fin, node->data->term);
    getline(fin, node->data->title);
    getline(fin, node->data->description);
    getline(fin, node->data->tktNum);
    getline(fin, node->data->location);
    getline(fin, node->data->lecDay);
    getline(fin, node->data->instructor);
    getline(fin, node->data->labLoc);
    getline(fin, node->data->labDay);
    getline(fin, node->data->labInstruct);
    getline(fin, node->data->units);
    getline(fin, node->data->preReqs);
    getline(fin, node->data->grade);
    header->length++;

    string blankLine;
    if(!getline(fin, blankLine))
    break;
    }
    fin.close();
}

我的 deleteData 函数

删除数据TN.cpp

#include "hw07.h"

void deleteDataTN(slist *&header)
{
    sentry *node, *temp;
    string ticketNum;
    ofstream fout;
    int index;
    bool found;
    found = false;
    index = 0;

    cout << "Ticket Number: ";
    getline(cin, ticketNum);

    node = header->first;
    while(index < header->length && !found)
    {
        if(node->data->tktNum == ticketNum)
        {
            found = true;
            free(node->data);
        }
        else
        {
             ++index;
             temp = node;
             node = temp->next;
         }
        fout.open("sbclassdb.txt");

    node = header->first;
    for(int i=0; i<header->length; ++i)
    {
        fout << node->data->term << endl;
        fout << node->data->title << endl;
        fout << node->data->description << endl;
        fout << node->data->tktNum << endl;
        fout << node->data->location << endl;
        fout << node->data->lecDay << endl;
        fout << node->data->instructor << endl;
        fout << node->data->labLoc << endl;
        fout << node->data->labDay << endl;
        fout << node->data->labInstruct << endl;
        fout << node->data->units << endl;
        fout << node->data->preReqs << endl;
        fout << node->data->grade << endl;

        temp = node;
        node = temp->next;
        fout << "\n";
    }
}

我用来读取文件的文本文件

sbclassdb.txt

Fall 2017
CS1A
Intro to Computer Science 1
11111
SM101
TTH 100PM
John Doe
SM102
TTH 300PM
John Doe
5
NA
A

Spring 2018
CS1B
Intro to Computer Science 2
22222
SM101
TTH 200PM
Jane Doe
SM102
TTH 300PM
Jane Doe
5
CS1A
NA

Spring 2018
CS4A
Into to Java for Computer Science
12345
BGS101
MWF 200PM
Bob Smith
BGS102
Bob Smith
4
CS1B
NA

【问题讨论】:

    标签: c++ pointers data-structures doubly-linked-list


    【解决方案1】:

    new 应该用delete 清理(而不是free 用于malloc

    struct sentry{stud *data;...} 可以更改为struct sentry{stud data;...}。而且不需要sentry::list会员:

    struct sentry
    {
        sentry *next;
        sentry *prev;
        stud data;
    };
    

    sentry::data 声明为指针没有任何好处。如果您只是将数据声明为stud data;,那么您不必使用new/delete 分配/释放。 (对于节点,您仍然需要 new/delete

    void deleteDataTN(slist *&amp;header)可以声明为void deleteDataTN(slist &amp;header),你只需调用deleteDataTN(myheader);

    不要使用while(!fin.eof()){...}。关于这个问题有很多 SO 主题。参见例如how-does-ifstreams-eof-work。我之前写了一个代码,我认为是错误的,这里是更正的版本:

    while(fin.good())
    {
        sentry *node = new sentry;
        if(header.first == nullptr)
        {
            node->prev = nullptr;
            node->next = nullptr;
            header.first = node;
            header.last = node;
        }
        else
        {
            header.last->next = node;
            node->prev = header.last;
            node->next = nullptr;
            header.last = node;
        }
        ...
    }
    

    要移除一个节点,你可以给slist添加一个函数:

    struct slist
    {
        ...
        void remove(sentry *node);
    };
    
    void slist::remove(sentry *node)
    {
        if(!node) return;
        if(!first) return;//empty list, do nothing
        if(first->next == nullptr)//deleting the only node
        {
            first = last = nullptr;
        }
        else if(node == last)//deleting the last node
        {
            last = node->prev;
            node->prev->next = nullptr;
        }
        else if(node == first)//deleting the first node
        {
            first = node->next;
            first->prev = nullptr;
        }
        else//deleting a node in the mid
        {
            node->prev->next = node->next;
            node->next->prev = node->prev;
        }
        length--;
        delete node;
    }
    

    现在您可以删除任何节点

    node = header.first;
    while(node)
    {
        if(node->data.tktNum == "xyz")
        {
            header.remove(node);
            break;
        }
        node = node->next;
    }
    

    【讨论】:

    • 再次感谢巴马克,这对我很有帮助。对于不必要的代码(如哨兵*数据)是因为我的教授希望我们熟悉分配和释放内存,否则我会失分。
    最近更新 更多