如何解决最后一个位置的链表插入错误
我用 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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。