我使用malloc来分配列表中的新节点,但是我遇到了代码中某一部分的错误; 以下解决方案仅适用于删除和插入
#include <stdio.h>
#include <malloc.h>
struct Node{
int value;
struct Node * Next;
struct Node * Previous;
};
typedef struct Node Node;
struct List{
int Count;
int Total;
Node * First;
Node * Last;
};
typedef struct List List;
List Create();
void Add(List a,int value);
void Remove(List a,Node * b);
List Create()
{
List a;
a.Count=0;
return a;
}
void Add(List a,int value)
{
Node * b = (Node *)malloc(sizeof(Node));
if(b==NULL)
printf("Memory allocation error \n");
b->value=value;
if(a.Count==0)
{
b->Next=NULL;
b->Previous=NULL;
a.First=b;
}
else
{
b->Next=NULL;
b->Previous=a.Last;
a.Last->Next=b;
}
++a.Count;
a.Total+=value;
a.Last=b;
}
void Remove(List a,Node * b)
{
if(a.Count>1)
{
if(a.Last==b)
{
b->Previous->Next=NULL;
}
else
{
b->Previous->Next=b->Next;
b->Next->Previous=b->Previous;
}
}
free(b);
}
在删除功能中,在最后一个条件下,我不确定是否使用b-&gt; Next-&gt;上一个是可以的,并且可以使用;当使用 - &gt;运算符,我是关于节点指针还是它的值?
答案 0 :(得分:0)
简短回答:是的,b->Next->Previous
很好 - 它是struct Node*
,就像右侧b->Previous
一样。
我认为您的错误在于Count
的处理:它增加Add()
,但Remove()
不会减少它。事实上,由于列表本身只需知道它是否为空,您可以将其删除,而不是查看a.First == NULL
。 (您的a.Count == 1
测试同样可以替换为a.First != NULL && a.First->Next == NULL
测试。)
如果您在API中承诺Count
,则可以在列表本身正常工作时将其添加回来。相同的“删除然后添加”可能对Total
有用。把它们都想象成缓存。
更好的解决方案是实现循环列表:
struct List
{
Node Anchor;
//...
};
List Create()
{
List l;
l.Anchor.Next = l.Anchor.Previous = &l;
return l;
}
bool IsEmpty(List const* l)
{
// Both or neither point at 'l'.
assert((l->Anchor.Next == l) == (l->Anchor.Previous == l));
return l->Anchor.Next == l;
}
// Add a node 'n' to some list after 'ln'.
void AddAfter(Node* n, Node* ln)
{
n->Previous = ln;
n->Next = ln->Next;
n->Next->Previous = n->Previous->Next = n;
}
Node* Remove(Node* n)
{
n->Previous->Next = n->Next;
n->Next->Previous = n->Previous;
n->Next = n->Previous = n; // nice and proper
return x;
}
现在您需要特殊情况下的空列表。我让Remove()
返回节点本身,以便在列表之间移动节点(AddAfter(Remove(somenode), &otherlist.Anchor)
)或删除和删除注释(free(Remove(somenode))
)。
这里的一个瑕疵是我的Anchor
节点现在浪费空间用于永远不会被使用的数据 - 但这很容易解决。