c++ - 在链表中添加列表项或节点
问题描述
我尝试使用以下 C++ 代码对链表项进行排序,同时从键盘插入值。在这里,我想使用 while 循环在一个插入函数的开头、中间某处和结尾插入值。我只关注如何通过使用逻辑运算找到确切位置来插入和删除。你能帮我编写一个可以在C++中插入项目时排序的链表吗
#include <iostream>
using namespace std;
struct listItem
{
//creating a node
int data;
struct listItem *next;
};
//function declaration
bool Initialize(listItem *head);
char menu();
void insertFirst(listItem *&head, listItem *&temp, int item);
void Insert(listItem *&head, listItem *&temp, int item);
void search(listItem *&head, listItem *&temp);
void deleteItem(listItem *&head, listItem *&temp);
void traverse(listItem *curr);
//function definition
bool Initialize(listItem *head)
{
//Initialize head and temp value to null
listItem *head = NULL;
listItem *temp = NULL;
}
char menu()
{
//menus
char choice;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~\n";
cout<<" Menu"<<endl;
cout<<" ........\n";
cout<<"1. Add an Item\n";
cout<<"2. Remove an Item\n";
cout<<"3. Search an Item\n";
cout<<"4. Traverse an Item\n";
cout<<"5. Exit\n";
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~\n";
cin>>choice;
return choice;
}
//function to insert items
void Insert(listItem *&head, listItem *&temp, int item)
{
// check if the linked list is null
listItem *curr = new listItem;
if(head == NULL)
{
curr->data = item;
curr->next =NULL;
temp = curr;
head = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data > item)
{
curr->data = item;
curr->next = temp->next;
temp = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data < item && curr->next != NULL)
{
while (curr->data < item)
curr = curr->next;
temp->next = curr;
curr->data = item;
curr->next = temp;
temp = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data < item)
{
while(head->data < item && curr->next == NULL)
curr = curr->next;
curr->data = item;
curr->next = NULL;
temp = curr;
}
else
cout<<item<<" is already there!!!\n";
}
void search(listItem *&head, listItem *&temp)
{
cout<<"NO code for searching item"<<endl;
}
void deleteItem(listItem *&head, listItem *&temp)
{
if(Initialize(head))
cout<<"The list is already Empty\n";
else if(head == temp)
{
delete head;
head = NULL;
temp = NULL;
}
else
{
listItem *curr = new listItem;
head = head->next;
delete curr;
}
}
void traverse(listItem *curr)
{
if(Initialize(curr))
cout<<"The list is already Empty\n";
else
{
cout<<"The list contains:\n";
while(curr != NULL)
{
cout<<curr->data<<endl;
curr = curr->next;
}
}
}
int main()
{
bool Initialize(head)
char choice;
int item;
do
{
choice = menu();
switch(choice)
{
case '1': cout<<"Please enter a number :";
cin>>item;
Insert(head, temp, item);
break;
case '2': //cout<<"Enter a number to delete :";
//cin>>item;
deleteItem(head, temp);
break;
case '3': search(head, temp);
break;
case '4': traverse(head);
break;
default: cout<<"System exit\n";
}
}
while(choice != '5');
return 0;
}
解决方案
插入节点。首先...代码!
#include <iostream>
struct listItem
{
//creating a node
int data;
struct listItem *next;
};
//function to insert items
void Insert(listItem *&head, int item)
{
listItem **curr = &head; // start at head
while (*curr != NULL // while there is a node
&& (*curr)->data <= item ) // and the node goes before the new node
{
curr = &(*curr)->next; // get next node
}
*curr = new listItem{item, *curr}; // insert the new node
}
int main()
{
listItem * head = NULL; // empty linked list head
Insert(head, 1); // test insert to empty list
Insert(head, 0); // insert at head
Insert(head, 3); // insert at end
Insert(head, 2); // insert in the middle
}
我删除了所有不必要的代码以专注于插入逻辑。您应该始终使用堆栈溢出问题来执行此操作。为了降低问题中的噪音,创建一个简单的程序来说明问题并且不做任何其他事情。阅读最小可复制示例以获取更多信息和灵感。
代码几乎不言自明:循环遍历列表,直到找到插入节点的位置,然后插入节点,但有两个小技巧。
有head
节点,也有next
节点。两者都做同样的工作:指向列表中的下一个节点。由于它们有不同的名称,我们需要不同的代码来处理它们。但是,如果我们可以使head
所有next
节点都具有相同的名称呢?然后他们可以拥有完全相同的代码。那curr
是工作。现在无论curr
是 ishead
还是 a都没有关系next
。大多数函数的代码只是......消失了。不存在的代码没有错误。
如果您迭代到需要提前插入的节点,则插入单链表的另一个问题是,您已经丢失了对它之前的节点的跟踪。要保持链接,您必须拥有前一个节点的next
指针(或head
)。您可以维护指向前一个节点的指针,但这不起作用,head
因为没有head
节点,因此您破坏了第一个技巧并以一些几乎重复的代码结束。但是,如果您抽象出节点并存储地址head
或next
指针,则您将有两条信息合二为一:插入点和插入点之后的节点。和
listItem **curr;
curr
指向我们要放置新节点的位置,并且*curr
是它之后的节点。所以
while (*curr != NULL // while there is a node
&& (*curr)->data <= item ) // and the node goes before the new node
{
curr = &(*curr)->next; // get next node
}
遍历列表,直到我们找到列表中的最后一个节点*curr
is NULL
,或者位于*curr
我们要插入的节点之后的数据,然后
*curr = new listItem{item, *curr};
创建一个新节点,该节点链接到后面的节点,并将这个新节点分配给插入点处的指针。
*curr
,指向列表中下一项的指针,设置为指向 a new
listItem
,就像 . 的任何其他用法一样new
。
twist 是listItem
一个非常简单的数据结构,可以利用聚合初始化来初始化listItem
的成员。大括号listItem
按照它们在结构中声明的顺序包含我想要的值。第一个成员变量 ,data
设置为item
,第二个成员变量 ,next
设置为 的当前值*curr
,即列表中的下一项。
对于一个很小的时间实例,您将拥有*curr
和next
新的listItem
指向相同listItem
的,然后=
操作员更新*curr
指向新创建的指向listItem
。
把它画在一张纸上,你会看到发生了什么。
推荐阅读
- javascript - 在反应类基础组件中设置 setTimeOut
- strapi - 我已经定制了 Strapi 控制器,但出现错误
- java - Jenkins 在自己的文件夹中为多模块项目寻找依赖项目包文件
- django - 将表单添加到表单集的子元素
- javascript - 上传图像时出现“无法识别的内容编码类型”错误
- functional-programming - 在 Elixir 中编写函数来测量另一个函数的好方法是什么
- javascript - 如何使用扩展运算符更新深拷贝对象的每个值
- javascript - 创建单独的库存显示
- python-3.x - OpenSSL - Raspberry Pi4 无法与 Windows 系统上的服务器通信
- excel - 更新另一个单元格时自动将日期/时间添加到一个单元格