俺也不多说: 连表最大的意义在于伸缩性, 可以任意添加, 删除, 插入而没有额外的性能损失.
简单的点评一下 45 楼的单向连表:
.) start 节点没有使用上
. ) 连表没有体现出如何删除和添加, 这才是重点所在.
. ) 单向连表删除旧节点,添加新节点, 会有额外的性能惩罚, 因为当前节点只有next, 而没有previous node, 所以只能遍历节点。
双向linked list:
struct listEntry{
char value;
struct listEntry *next;
struct listEntry *previous; //关键之处
}start, *header, *tail, *node;
void LinkList_Init()
{
header = &start;
tail = header;
header->next = NULL;
header->previous = NULL;
}
void LinkList_AddNode(struct listEntry* newNode) //newNode 在子程序外产生。
{
tail->Next = newNode;
newNode->next = NULL;
newNode->previous = tail;
tail = newNode; //新节点成为新尾巴
}
void LinkList_DeleteNode() //被删除的node 在子程序外处理, 如销毁等
{
if (tail->previous != NULL) {
tail = tail->previous;
tail->nexe = NULL;
}
}
这样, 可以使用45楼的连表解决更多数据输入的问题: 例如再加入一个数据:
node = (struct listEntry *)malloc(sizeof(struct listEntry));
node->value = input;
LinkList_AddNode(node);
或者简单的实现circular buffer, 把尾巴砍下来作为头:
ASSERT(tail->previous != NULL); //确认至少有2个node;
node = tail;
tail = tail->previous;
tail->next = NULL; //确保可以遍历.
header->previous = node;
node->next = header;
node->previous = NULL;
tail->value = input;
另外,双向连表很容易解决插入节点的问题, 这里就不讲了. |