qq_45735316 2020-09-26 21:06 采纳率: 94.1%
浏览 188
已采纳

实在看不懂这个函数的最后一步,如果想让last node的指针指向t node不是应该s=t吗?为什么是s->next=t?

template<class T>        //单链表逆置 
void Reverse(Node<T>* s)//s为线性表a头结点
{
    Node<T>* p = s->next;//p指向第一个结点
        s->next = NULL;//头结点指向空
    while (p != NULL)
    {
        Node<T>* t = p;//t为工作指针
        p = p->next;//p后移
        t->next = s->next;//
        s->next = t;//???
    }
}

#include <iostream>
using namespace std;

template<class T>
struct Node//结点
{
    T data;//数据域
    Node<T>* next;//指针域:下一个元素的地址
};

template<class T>
class LinkList//线性表类
{
public:
    LinkList();
    LinkList(T a[], int n);
    ~LinkList();
    void PrintList();
    T Get(int i);
    void Insert(int i, T x);
    void Delete(int i);
public:
    Node<T>* first;//单链表(线性表的第一个元素?)
};

template<class T>
LinkList<T>::LinkList()//默认构造函数
{
    first = new Node<T>;//第一个元素为新创建结点对象
    first->next = NULL;//第一个元素对象的指针域为空
}

template<class T>
LinkList<T>::LinkList(T a[], int n)//构造函数
{
    first = new Node<T>;
    Node<T>* r = first;//当前的结点指向线性表的第一个结点/元素
    for (int i = 0; i < n; i++)
    {
        Node<T>* s = new Node<T>;//创建下一个结点
        s->data = a[i];//结点的数据域为数组a的第i个元素
        r->next = s;//当前结点的指针域指向新创建的结点s
        r = s;//当前结点向后移
    }
    r->next = NULL;//最后一个结点的指针域为空
}

template<class T>
LinkList<T>::~LinkList()
{
    while (first != NULL)//一个个删除结点
    {
        Node<T>* q = first;//q赋值为当前结点
        first = first->next;//first赋值为下一个结点
        delete q;//删除当前结点
    }
}

template<class T>
void LinkList<T>::PrintList()
{
    Node<T>* p = new Node<T>;//p为新创建的结点
    p = first->next;//???工作指针p初始化,p指向当前结点的指针域/当前结点???
    while (p != NULL)
    {
        cout << p->data << " ";
        p = p->next;
    }
}

template<class T>
T LinkList<T>::Get(int i)
{
    Node<T>* p = first->next;
    int count = 1;
    while (p != NULL && count < i)
    {
        p = p->next;
        count++;
    }
    if (p == NULL) throw "查找位置异常";
    else return p->data;
}

template<class T>
void LinkList<T>::Insert(int i, T x)
{
    Node<T>* p = first;
    int count = 0;
    while (p != NULL && count < i - 1)
    {
        p = p->next;
        count++;
    }
    if (p == NULL) throw "插入位置异常";
    else
    {
        Node<T>* s = new Node<T>;
        s->data = x;
        s->next = p->next;
        p->next = s;
    }
}

template<class T>
void LinkList<T>::Delete(int i)
{
    Node<T>* p;
    int j;
    p = first; j = 0;  //工作指针p初始化
    while (p != NULL && j < i - 1)  //查找第i-1个结点
    {
        p = p->next;
        j++;
    }
    if (p == NULL || p->next == NULL) throw "删除位置异常";  //结点p不存在或结点p的后继结点不存在
    else {
        Node<T>* q;
        T x;
        q = p->next; x = q->data;  //暂存被删结点
        p->next = q->next;  //摘链
        delete q;
    }
}

template<class T>        //复制单链表 
Node<T>* Copy(Node<T>* s)//返回一个结构体?
{
    Node<T>* head = new Node<T>;
    Node<T>* r = head;//新线性表p的工作指针
    Node<T>* p = s;//线性表a的工作指针
    p = p->next;//p移到第一个结点
    while (p != NULL)
    {
        Node<T>* t = new Node<T>;//创造一个新结点
        t->data = p->data;//复制线性表a中的值
        r->next = t;//当前结点指向新创造的结点
        r = t;//工作指针移到新的结点
        p = p->next;//线性表a中的工作指针后移,同一个指针后移:p=p->next
    }
    r->next = NULL;

    return head;
}

template<class T>        //单链表逆置 
void Reverse(Node<T>* s)//s为线性表a头结点
{
    Node<T>* p = s->next;//p指向第一个结点
        s->next = NULL;//头结点指向空
    while (p != NULL)
    {
        Node<T>* t = p;//t为工作指针
        p = p->next;//p后移
        t->next = s->next;//
        s->next = t;//???
    }
}


int main()
{
    int a[] = { 1,2,3,4,5 };
    LinkList<int> test(a, 5);
    cout << "线性表a的初始状态:" << endl;
    test.PrintList();

    cout << endl << "复制线性表a到线性表p,再逆置线性表a。" << endl;
    Node<int>* p = new Node<int>;
    p = Copy(test.first)->next;//Copy返回一个结点
    Reverse(test.first);


    cout << "线性表a的状态:" << endl;
    test.PrintList();

    cout << endl << "线性表p的状态:" << endl;
    while (p != NULL)
    {
        cout << p->data << " ";
        p = p->next;
    }

    getchar();
    return 0;
}
  • 写回答

2条回答 默认 最新

  • 泡视界 2020-09-27 16:40
    关注

    不是,这个问题你又单独提了一遍啊?

    问题的根本是你需要一个容器来记录last node。这一点你是不是已经没疑问了?

    如果上面你没问题了,那么:
    你的疑问是这个容器为什么是 s->next 而不是 s 对吧?

    你先看一下定义 s->next 是什么类型, s 又是什么类型?
    你有没有发现他们是同一个类型, 都是 Node*
    这说明 s->next 和 s 本质上没有任何区别,都是一种容器。

    那么用什么他们两来记录last node,都可以啊,这一点你明白吗?

    如果上述两点你都明白,那么最后
    问题是为什么用 s->next 而不用 s;

    你看一下我有注释的那一句
    void Reverse(Node* s)
    {
    Node* p = s->next;
    s->next = NULL; // 用 s->next 记录last node, 此时last node没有,所以因改为NULL
    while (p != NULL)
    {
    Node* t = p;
    p = p->next;
    t->next = s->next;
    s->next = t;
    }
    }

    那么既然前面你用了s->next ,所以后面你当然需要用s->next来循环啊。

    如果你想用 s 也可以,那么在初始化的时候你就要有相应的改动, s = NULL。

    这么说你明白了吗?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已采纳回答 9月25日

悬赏问题

  • ¥15 有两个非常“自以为是”烦人的问题急期待大家解决!
  • ¥30 STM32 INMP441无法读取数据
  • ¥100 求汇川机器人IRCB300控制器和示教器同版本升级固件文件升级包
  • ¥15 用visualstudio2022创建vue项目后无法启动
  • ¥15 x趋于0时tanx-sinx极限可以拆开算吗
  • ¥15 pyqt信号槽连接写法
  • ¥500 把面具戴到人脸上,请大家贡献智慧,别用大模型回答,大模型的答案没啥用
  • ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
  • ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
  • ¥30 c#打开word开启修订并实时显示批注