我写了一些代码,可以创建一个链表,将元素插入到开头或结尾,然后显示它。
struct ListElem
{
int info;
ListElem * next;
};
// shortcut for list = pointer to a list element
typedef ListElem * List;
// empty list is a Null Pointer
const List emptyList = 0;
void printList(List lst) {
for (; lst!= 0; lst = lst->next) {
cout << lst->info << endl;
}
}
void insertElem(List& lst, int info) {
ListElem *ptrElem = new ListElem;
ptrElem->info = info;
ptrElem->next = lst;
lst = ptrElem;
}
void insertLast(List& lst, int info) {
ListElem *ptrElem = new ListElem;
ptrElem->info = info;
ptrElem->next = NULL;
if (lst == emptyList) {
insertElem(lst, info);
return;
}
else {
while (lst ->next) {
lst = lst->next;
}
lst->next = ptrElem;
}
}
我尝试了main上的insertLast函数:
int main()
{
// fill List with values 1 to 10
List list1 = emptyList;
for (int value = 1; value <= 10; value++)
{
//insertElem( list1, value );
insertLast(list1, value);
}
//print list
printList(list1); // should provide sequence 1 2 3 ... 10
但是出于某种原因,printList仅显示9和10,而不是1,2,3,..,10。仅在insertLast中会发生此问题。 insertElem似乎工作正常。
答案 0 :(得分:1)
问题在于,在insertLast()
内部,您通过引用传递了列表参数。也就是说,对列表所做的每个更改都将在函数外部可见。在这些行上-while (lst ->next) {lst = lst->next;}
,您将更改列表引用,因此列表的第一个节点会随着每次添加而被修改。
解决方案是采用一个辅助迭代器节点,以迭代您的列表,或按值传递您的List,像现在一样更改列表,然后返回修改后的副本。
下面是insertLast()
方法,该方法经过重写以使用辅助节点迭代列表:
void insertLast(List& lst, int info) {
ListElem *ptrElem = new ListElem;
ListElem *aux = lst;
ptrElem->info = info;
ptrElem->next = NULL;
if (lst == emptyList) {
insertElem(lst, info);
return;
}
else {
while (aux ->next) {
aux = aux->next;
}
aux->next = ptrElem;
}
}
答案 1 :(得分:0)
此行为的原因是,在您的函数调用最后插入元素的函数之后,发生的事情是您的链表标头开始指向链表的倒数第二个元素,而不是链表的第一个元素。
在您的函数中,此方法的解决方法很简单:最后插入元素,只需将一个临时变量设置为等于链表标题,然后使用此临时变量遍历链表,而无需修改您要的链表标题作为函数参数传递。
答案 2 :(得分:0)
这是因为您使用的引用非常糟糕 查看您的insertLast函数
void insertLast(List& lst, int info) {
ListElem *ptrElem = new ListElem;
ptrElem->info = info;
ptrElem->next = NULL;
if (lst == emptyList) {
insertElem(lst, info);
return;
}
else {
while (lst ->next) {
lst = lst->next;
}
lst->next = ptrElem;
}
您将lst设置为最后一项,而lst是引用,因此在您的主要功能list1中已更改,您失去了列表 尝试:
void insertLast(List& lst, int info) {
ListElem *ptrElem = new ListElem;
List* newlst = lst;
ptrElem->info = info;
ptrElem->next = NULL;
if (lst == emptyList) {
insertElem(lst, info);
return;
}
else {
while (newlst ->next) {
newlst = newlst->next;
}
newlst->next = ptrElem;
}
答案 3 :(得分:0)
两个问题:
在insertLast
函数的开头,您总是创建一个新元素,关于yu仅当它不是列表中的第一个元素时才使用它。在这种情况下,您总是会发生内存泄漏。
使代码运行异常的第二个问题是,您将列表的标题更改为指向每个插入中最后一个位置之前的位置。要避免这种情况,您可以使用ListElem
指针,该指针将指向列表的开头,对此指针所做的更改将对原始列表的开头指针没有影响。
此功能将为您完成工作:
void insertLast(List& lst, int info) {
if (lst == emptyList) {
insertElem(lst, info);
return;
}
else {
ListElem *ptrElem = new ListElem;
ptrElem->info = info;
ptrElem->next = NULL;
ListElem* temp = lst;
while (temp->next) {
temp = temp->next;
}
temp->next = ptrElem;
}
}
答案 4 :(得分:0)
您的方法insertLast
修改输入lst,因此它指向main中for循环末尾的最后一个元素。这就是printList
仅给您最后两个数字的原因。
可以在一个功能中完成。如果您想在前面添加元素,则需要另一个,但这不是您的问题。
void insertElem(List& lst, int info) {
List elemntToInsert = new ListElem();
elemntToInsert->info = info;
elemntToInsert->next = nullptr;
//Check if input is null list
if (lst == nullptr)
{
lst = elemntToInsert;
}
else //Else append at the end
{
List lastElement = lst;
while (lastElement->next != nullptr)
lastElement = lastElement->next;
lastElement->next = elemntToInsert;
}
}