最后一个位置的链表插入错误

问题描述

我用 C++ 编写了一个链表插入程序。当我添加一个函数在链表的最后一个位置插入一个节点时,我得到了一个奇怪的输出。似乎正在输出地址。这是我的代码。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane fx:id="anchor" onKeyPressed="#keyPressed" prefHeight="650.0" prefWidth="750.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Sample2">
   <children>
      <ImageView fx:id="img3" fitHeight="50.0" fitWidth="50.0" layoutX="100.0" layoutY="100.0" onKeyPressed="#keyPressed" pickOnBounds="true" preserveRatio="true" style="-fx-view-order: 10;" translateZ="100.0">
         <image>
            <Image url="@../Şirine.png" />
         </image>
      </ImageView>
   </children>
</AnchorPane>

我得到的输出是:

#include <iostream>
using namespace std;

class Node
{
public:
   int data;
   Node *next;
   Node(int d)
   {
     data=d;
   }
};

class operations
{
public:
    Node *head;
    Node *ptr;

    void insertfirst(int d)
    {
        Node *newnode = new Node(d);
        newnode->next=NULL;
        if(head==NULL)
        {
            head=newnode;
        }
        else
        {
            newnode->next=head;
            head=newnode;
        }
    }

    void display()
    {
        Node *ptr;
        ptr=head;
        while(ptr!=NULL)
        {
            cout<<ptr->data<<" ";
            ptr=ptr->next;
        }
    }

    void insertafter(int key,int d)
    {
        Node *ptr;
        ptr=head;
        while(ptr->data!=key)
        {
            if(ptr->next==NULL)
            {
                cout<<"Key not found";
                return;
            }
            ptr=ptr->next;
        }
        Node *newnode=new Node(d);
        newnode->next=ptr->next;
        ptr->next=newnode;
    }

    void insertlast(int d)
    {
        Node *ptr;
        ptr=head;
        Node *newnode = new Node(d);
        newnode->next=NULL;
        while(ptr->next!=NULL)
        {
            ptr=ptr->next;
        }
        ptr->next=newnode;
    }
};

int main()
{
    operations o;
    o.insertfirst(4);
    o.insertfirst(3);
    o.insertafter(3,5);
    o.insertlast(1);
    o.display();
    return 0;
}

我的预期输出是:

3 5 4 1577825 1

我应该怎么做才能获得预期的输出?

解决方法

有两种方法可以处理此类问题。

  • 在调试器中运行您的程序。这通常是解决复杂问题的最快方法,因此您应该计划尽快熟悉调试器的使用。由于调试器是一个相当复杂的工具,而且许多流行的调试器都不是那么容易使用,您可能不想针对这个特定问题使用一个。但从长远来看:了解如何使用调试器。
  • 在纸上运行您的程序。特别是对于链表,这种方法是纯金的。在纸上绘制节点,并绘制箭头以跟踪哪个指针指向什么。然后一行一行地完成你的程序并随着你的进行更新绘图。重要的是你不要在这里偷工减料,而是真正一行一行地走,仔细地追溯程序的各个步骤,即使起初看起来很乏味。通过这种方式,问题应该很快就会显现出来。如果您仍然遇到问题,请在您的代码中添加额外的调试输出,作为健全性检查您的纸质模拟确实准确。如果您确实在纸上犯了一个错误,额外的输出应该可以帮助您发现它。

由于第二种方法需要一些体力劳动,因此尽可能减少表现出不良行为的程序通常是值得的。例如,如果您从 o.insertfirst(3); 中删除 main 行,您是否仍然看到问题?您能否在问题消失之前删除更多行?

一旦您以这种方式缩小了错误范围,请抓起一张纸试一试。不要害怕这项工作,以这种方式修复错误是软件工程的基础,而这个特殊问题是磨练您在这方面技能的绝佳练习。

愉快的 bug 狩猎!

,

您的问题在于您的函数 insertfirst()。您不会始终如一地初始化节点的所有成员,因此当您添加值为 4 的第一个节点时,head 并不总是 NULL(在 C++ 中使用 nullptr),因此您有值为 4 的节点指向垃圾指针。

正如在另一个答案中提到的,使用调试器单步执行代码会很快发现这一点。

C++ 已经取得了长足的进步,不要像 C 一样对待它。使用构造函数(以及默认成员初始化),将您的列表类命名为 List 而不是操作。实际上封装您的数据。了解 3/5/0 规则。了解迭代器。 C++ 中的正确链表是很多原则和模式的结晶。

=== 可选 ===

#include <iostream>
#include <memory>

/*
 * List Declaration
 */
class List {
 public:
  List() = default;         // Default constructor
  List(const List& other);  // Copy ctor
  List(List&& other);       // Move ctor
  ~List();                  // Destructor

  // Iterators are an invaluable design pattern; they allow your class to
  // interact with the Standard Library
  class iterator;
  iterator begin();
  iterator end();

  // Naming changed to better match Standard Library behavior
  void push_front(int val);
  void push_back(int val);
  iterator insert(iterator pos,int val);
  iterator find(int val);

  void clear();

  List& operator=(List rhs);
  friend void swap(List& lhs,List& rhs);

 private:
  struct Node {
    int data;
    Node* next = nullptr;

    Node(int val) : data(val) {}
  };

  Node* m_head = nullptr;
  Node* m_tail = nullptr;

  // Helper functions
  void make_first_node(int val);
};

/*
 * List Iterator Declaration
 */
class List::iterator {
 public:
  iterator(Node* pos);
  int& operator*();
  iterator& operator++();
  bool operator==(iterator other);
  bool operator!=(iterator other);

 private:
  Node* m_pos;
};

/*
 * List Implementation
 */
List::List(const List& other) {
  make_first_node((other.m_head)->data);

  Node* walker = (other.m_head)->next;
  while (walker) {
    push_back(walker->data);
  }
}

List::List(List&& other) : List() { swap(*this,other); }

List::~List() { clear(); }

typename List::iterator List::begin() { return iterator(m_head); }

typename List::iterator List::end() { return iterator(nullptr); }

void List::push_front(int val) {
  if (!m_head) {
    make_first_node(val);
    return;
  }

  Node* tmp = new Node(val);
  tmp->next = m_head;
  m_head = tmp;
}

void List::push_back(int val) {
  if (!m_head) {
    make_first_node(val);
    return;
  }

  m_tail->next = new Node(val);
  m_tail = m_tail->next;
}

typename List::iterator List::insert(iterator pos,int val) {
  Node* walker = m_head;
  while (walker->next->data != *pos) {
    walker = walker->next;
  }

  Node* marker = walker->next;
  walker->next = new Node(val);
  walker->next->next = marker;

  return iterator(walker->next);
}

typename List::iterator List::find(int val) {
  Node* walker = m_head;
  while (walker) {
    if (walker->data == val) {
      return iterator(walker);
    } else {
      walker = walker->next;
    }
  }

  return iterator(walker);
}

void List::clear() {
  Node* tmp = m_head;
  while (tmp) {
    m_head = m_head->next;
    delete tmp;
    tmp = m_head;
  }
  m_tail = nullptr;
}

List& List::operator=(List rhs) {
  swap(*this,rhs);

  return *this;
}

void List::make_first_node(int val) {
  m_head = new Node(val);
  m_tail = m_head;
}

// List Friend
void swap(List& lhs,List& rhs) {
  using std::swap;

  swap(lhs.m_head,rhs.m_head);
  swap(lhs.m_tail,rhs.m_tail);
}

/*
 * List Iterator Implementation
 */
List::iterator::iterator(List::Node* pos) : m_pos(pos) {}

int& List::iterator::operator*() { return m_pos->data; }

typename List::iterator& List::iterator::operator++() {
  m_pos = m_pos->next;

  return *this;
}

bool List::iterator::operator==(typename List::iterator other) {
  return m_pos == other.m_pos;
}

bool List::iterator::operator!=(typename List::iterator other) {
  return !(*this == other);
}

int main() {
  List list;
  list.push_front(4);
  list.push_front(3);
  // My insert() behaves like the Standard Library's,meaning before & not after
  list.insert(list.find(4),5);
  list.push_back(1);

  // The iterator implemented provides *just* enough functionality to allow
  // the class to be used in a range-based for loop
  for (auto i : list) {
    std::cout << i << ' ';
  }
  std::cout << '\n';
}
,

我没有看到任何逻辑问题,我认为应该通过删除公共“Node *ptr;”来修复您的代码变量定义。换句话说,您可能只需要在所有功能中本地添加此变量。

此外,如果您在 Node 构造函数中初始化 node->next =null ,那将是更好的做法。 这是您的代码,其中包含讨论的修改。

#include<iostream>
using namespace std;

class Node
{
   public:
   int data;
   Node *next;
   Node()
   {
     data=INT_MAX;
     next= NULL;
   }
   Node(int d)
   {
     data=d;
     next= NULL;
   }
};
    class operations
    {
        public:
        Node *head;
        operations() {
            head =NULL;
        }
        void insertfirst(int d)
        {
            Node *newnode = new Node(d);
        
        if(head==NULL)
        {
            head=newnode;
        }
        else
        {
            newnode->next=head;
            head=newnode;
        }
        
    }
    void display()
    {
        
        Node *ptr;
        ptr=head;
        
        while(ptr)
        {
            cout<<ptr->data<<" ";
            ptr=ptr->next;
        }
        
    }
    void insertafter(int key,int d)
    {
        Node *ptr;
        ptr=head;
        while(ptr->data!=key)
        {
            if(ptr->next==NULL)
            {
                cout<<"Key not found";
                return;
            }
            ptr=ptr->next;
        }
        Node *newnode=new Node(d);
        newnode->next=ptr->next;
        ptr->next=newnode;
    }
    void insertlast(int d)
    {
        Node *ptr;
        ptr=head;
        Node *newnode = new Node(d);
        while(ptr->next!=NULL)
        {
            ptr=ptr->next;
        }
        ptr->next=newnode;
    }
};
int main() {
    operations o;
    o.insertfirst(4);
    o.insertfirst(3);
    o.insertafter(3,5);
    o.insertlast(1);
    o.display();
    return 0;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...