云现山川 2024-04-02 21:55 采纳率: 33.3%
浏览 3
已结题

C++链表中的一些问题

主程序中的错误如何改正,及让程序正常运行,不使用空结点
cpp:

#include<iostream>
#include"list.h"
using namespace std;

class Complex
{
    double re, im;       //实部和虚部
    double len;          //复数的模
public:
    Complex(double re = 0, double im = 0)                  //构造
    {
        this->re = re; this->im = im;
    }
    friend ostream& operator << (ostream& os, const Complex& c)   //输出复数
    {
        os << c.re << " + " << c.im<<"i";
        return os;
    }
    friend istream& operator >> (istream& is, Complex& c)         //读入复数
    {
        is >> c.re >> c.im;
        return is;
    }

    //添加其他代码
    void operator=(Complex& p)
    {
        re = p.re;
        im = p.im;
    }

    bool operator==(Complex& p)
    {
        if (re == p.re && im == p.im)
            return 1;
        return 0;
    }

};

int main()
{
    List<Complex> clist;            //创建空的复数链表(不带链头空节点)
    cout << clist << endl;

    cout << endl;

    Complex c;

    cout << "...建立复数链表..." << endl << endl;
    cout << "输入6组复数并插入链表:" << endl;
    for (int i = 0; i < 6; i++)
    {
        cin >> c;                  //读入复数
        clist.insertRear(c);       //将复数插在链尾
    }
    cout << clist << endl;
    cout << endl;

    cout << "...测试查找一个关键字节点的前节点..." << endl << endl;
    cout << "输入待查找复数:" << endl;
    cin >> c;

    Node<Complex>* pFind = 0, *pFront = 0;      //关键字节点及其前节点的指针            
    pFind = clist.search(c);
    if (pFind)
    {
        pFront = clist.findFront(pFind);
    }

    cout << pFront->info << endl;               //输出前节点值

    Node<Complex>* pDel = clist.delP(pFront);         //

    cout << endl;

    cout << "...测试删除关键字节点..." << endl << endl;
    cout << "输入待查找复数:" << endl;
    cin >> c;

    pDel = clist.delData(c);
    if (!pDel)
        cout << c << "不在链表中" << endl;
    cout << clist << endl;
    
    return 0;
}


h:

#include <iostream>
using namespace std;

template <typename T> class List;
template <typename T> class Node
{
public:
    T info;               //节点数据
    Node<T> *link;        //节点指针
    Node() { link = 0; }   //创建空节点
    Node(const T&data)
    {
        info = data; link = 0;
    }      //创建节点并初始化
    void InsertAfter(Node<T>*);     //将参数节点接在本节点后
    Node<T>* RemoveAfter();         //删除本节点的后节点,返回删除节点地址,若为空,则表示无法删除
    friend class List<T>;
};

template <typename T>
void Node<T>::InsertAfter(Node<T>* p)
{
    p->link = link;
    link = p;
}

template <typename T>
Node<T>* Node<T>::RemoveAfter()
{
    Node<T>* after = link;          //指向本节点的后节点
    if (after)
        link = after->link;
    return after;
}

template <typename T>
class List
{
    
public:
    Node < T > *head, *tail;
    List()                         //构造空链表,无链头空节点
    {
        head = 0;                    //添加代码
        tail = 0;
    }

    ~List()                        //析构链表 
    {
        while (head->link != NULL)        //添加代码
        {
            Node<T>* temppoint;
            temppoint = head->link;
            head->link = temppoint->link;
            delete temppoint;

        }
        tail = head;
        delete head;
        
    }

    bool isEmpty() { return head == 0 && tail == 0; }          //判断是否空链表
    friend ostream& operator << (ostream& os,  List<T>& list)   //重载运算符用于输出链表
    {
        if (list.isEmpty()) os << "空链表!" << endl;
        else
        {
            Node<T> *p =list.head;
            while (p)
            {
                os << p->info << "  ";
                p = p->link;
            }
        }
        return os;
    }

    //添加声明:将数据节点插在链尾
    void insertRear(T k);
    //添加声明: 在链表中查找数据节点,返回节点指针
    List<T>* search(Node<T> k);
    //添加声明:删除链表中给定节点(给出待删除节点地址)
    void delP(Node<T>* point);
    //添加声明:删除链表中给定数据节点(给出待删除数据)
    void delData(Node<T> k);
    //添加声明:获取给定节点的前节点
    List<T>* findFront(Node<T>* p);
    
};

//添加代码:补充以上函数声明的定义
template <typename T>
void List<T>::insertRear(T k)                    //将数据节点插在链尾
{
    /*if (head == 0 && tail == 0)
    {
        head->info = k;
        tail = head->link;
    }*/
    Node<T>* temppoint=NULL;
    temppoint->info = k;
    temppoint->link =tail->link;
    tail->link = temppoint;
    tail = temppoint;
    /*if (head == 0 && tail == 0)
    {
        head = new Node<T>;
        tail = head;
        tail->info = k;
        tail->link = 0;
        return;
    }
    tail->link = new Node<T>;
    tail = tail->link;
    tail->info = k;
    tail->link = 0;
    return;*/
}

template <typename T>
List<T>* List<T> ::search(Node<T> k)            //在链表中查找数据节点,返回节点指针
{
    Node<T>* temppoint = head;
    while (temppoint->info != k&&temppoint->link!=NULL)
    {
        temppoint = temppoint->link;
    }
    if (temppoint->info == k)
    {
        cout << "找到该数据节点" << endl;
        return temppoint;
    }
    else if (temppoint->info != k)
    {
        cout << "该链表中不含该元素" << endl;
        return 0;
    }
}

template <typename T>
void List<T>::delP(Node<T>* point)                //删除链表中给定节点(给出待删除节点地址)
{
    Node<T>* temppoint;
    temppoint = point.findFront();
    if (point->link != NULL)
    {
        temppoint->link = point->link;
    }
    else if (point->link == NULL)
    {
        temppoint->link = NULL;
    }
    delete point;
}

template <typename T>
void List<T>::delData(Node<T> k)                //删除链表中给定数据节点(给出待删除数据)
{
    Node<T>* temppoint = search(k);
    delP(temppoint);
    
}

template <typename T>
List<T>*List<T>:: findFront(Node<T>* p)                    //获取给定节点的前节点
{
    Node<T>* temppoint = head;
    while (temppoint->link != p)
    {
        temppoint = temppoint->link;
    }
    return temppoint;
}

  • 写回答

25条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-02 21:55
    关注
    获得0.30元问题酬金

    引自免费微信小程序:皆我百晓生

    针对您提供的C++代码,在main.cpplist.h文件中有一些逻辑错误和未完成的功能实现。以下是修复这些问题后的代码:

    main.cpp

    #include<iostream>
    #include"list.h"
    using namespace std;
    
    class Complex
    {
        double re, im;       //实部和虚部
        double len;          //复数的模
    
    public:
        Complex(double re = 0, double im = 0) : re(re), im(im) {}
        friend ostream& operator << (ostream& os, const Complex& c)   //输出复数
        {
            os << c.re << " + " << c.im << "i";
            return os;
        }
        friend istream& operator >> (istream& is, Complex& c)         //读入复数
        {
            is >> c.re >> c.im;
            return is;
        }
    
        // 添加相等比较运算符,使用const引用以避免不必要的拷贝
        bool operator==(const Complex& p) const
        {
            return re == p.re && im == p.im;
        }
    };
    
    int main()
    {
        List<Complex> clist;            // 创建空的复数链表(不带链头空节点)
    
        cout << "空链表:" << endl;
        cout << clist << endl;
    
        cout << endl;
    
        Complex c;
    
        cout << "...建立复数链表..." << endl << endl;
        cout << "输入6组复数并插入链表:" << endl;
        for (int i = 0; i < 6; i++)
        {
            cin >> c;                  // 读入复数
            clist.insertRear(c);       // 将复数插在链尾
        }
        cout << "当前链表:" << endl;
        cout << clist << endl;
        cout << endl;
    
        cout << "...测试查找一个关键字节点的前节点..." << endl << endl;
        cout << "输入待查找复数:" << endl;
        cin >> c;
    
        Node<Complex>* pFind = clist.search(c);
        Node<Complex>* pFront = clist.findFront(pFind);
    
        if (pFind)
        {
            cout << "前节点值:" << pFront->info << endl;  // 输出前节点值
        }
        else
        {
            cout << "未找到指定复数对应的节点。" << endl;
        }
    
        // 删除操作应在确保找到节点之后进行
        if (pFind)
        {
            clist.delP(pFind);
        }
    
        cout << endl;
    
        cout << "...测试删除关键字节点..." << endl << endl;
        cout << "输入待查找复数:" << endl;
        cin >> c;
    
        pDel = clist.delData(c);
        if (!pDel)
            cout << c << " 不在链表中" << endl;
        else
            cout << "已成功删除复数:" << c << endl;
    
        cout << "当前链表:" << endl;
        cout << clist << endl;
    
        return 0;
    }
    

    list.h

    修改List::insertRear方法的实现:

    template <typename T>
    void List<T>::insertRear(T k)
    {
        Node<T>* newNode = new Node<T>(k);
        if (isEmpty())
        {
            head = newNode;
            tail = newNode;
        }
        else
        {
            tail->link = newNode;
            tail = newNode;
        }
    }
    

    同时,修复List::search方法的返回类型,并修正其内部逻辑:

    template <typename T>
    Node<T>* List<T>::search(const T& k)            // 在链表中查找数据节点,返回节点指针
    {
        Node<T>* temppoint = head;
        while (temppoint && temppoint->info != k)
        {
            temppoint = temppoint->link;
        }
        return temppoint;  // 返回查找到的节点或NULL(未找到时)
    }
    

    另外,由于findFront函数已经找到了给定节点的前节点,所以在delP函数中不需要再调用findFront

    template <typename T>
    void List<T>::delP(Node<T>* point)                // 删除链表中给定节点(给出待删除节点地址)
    {
        if (point == nullptr || point == head)
            return;
    
        Node<T>* frontNode = point->link ? point->link->findFront(point) : head;
        frontNode->link = point->link;
        if (point == tail)
            tail = frontNode;
    
        delete point;
    }
    

    注意:上述改动仅修复了部分错误,还应该对其他可能存在的问题进行检查,例如内存泄漏等问题。在实际编程中,对于链表的操作函数应当更加谨慎处理边界条件。同时,为了代码的健壮性,可以考虑在链表类中增加一些错误检查机制,比如当尝试从空链表中删除节点时抛出异常或返回错误信息。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月10日
  • 修改了问题 4月2日
  • 创建了问题 4月2日

悬赏问题

  • ¥15 网络科学导论,网络控制
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)