学海无涯~~
看该文章需要有那么一点点的理论知识,写的不好,本文如有问题请各位大佬指出。
代码传送门(代码写得不完善,有兴趣的朋友可以看看) gitee.com/huang-yuanc…
该代码编辑编译环境为 apple m1 机器 在其他环境下没试过,有兴趣的朋友可以尝试一下
简介
该文章简单的介绍什么是双向链表,如何实现一个简单的双向链表,添加,删除,查找。
双向链表的 添加
个人习惯用结构体(不了解的可以google 一下),方便。
例如定义一个结构体。
struct list_node
{
int count;
list_node *head;
list_node *next;
};
添加一个节点。方式很多,这里采用永远记录最后一个节点,直接添加(不采用循环遍历方式)。
好处:效率高。坏处:不能在添加的时候做排序。
循环遍历方式,好处:可以在添加时做好排序。坏处:效率极低。
代码如下:
list_node *temp_node_ = nullptr;
temp_node_ = static_cast<list_node *>(malloc(sizeof(list_node)));
if(temp_node_ == nullptr)
{
return false;
}
else
{
temp_node_->count = count_paramter;
temp_node_->head = nullptr;
temp_node_->next = nullptr;
}
if(_head_node == nullptr)
{
_head_node = _end_node = temp_node_;
}
else
{
if(_end_node != nullptr)
{
_end_node->next = temp_node_;
temp_node_->head = _end_node;
_end_node = temp_node_;
}
else
{
return false;
}
}
_node_num++;
双向链表的 删除
删除双向链表需要考虑三点 头 中 尾,这三点删除的方式会有不同,但和单向链表一样。
1.删除头 把下一节定义为头节点,并删除原始头节点。
2.删除尾 把尾的上一节点修改next参数赋值为nullptr,并删除原始尾节点。
3.删除中 把需要删除节点的父节点子节点赋值为删除节点的子节点,并把子节点的父节点赋值为删除节点的父节点。
代码如下:
list_node *last_node_ = nullptr;
list_node *temp_node_ = _head_node;
bool b_ret_ = false;
while (temp_node_ != nullptr)
{
if(temp_node_->count == count_paramter)
{
if(last_node_ == nullptr)
{
_head_node = temp_node_->next;
_head_node->head = nullptr;
}
else
{
if(temp_node_->next == nullptr)
{
last_node_->next = nullptr;
_end_node = last_node_;
}
else
{
temp_node_->next->head = temp_node_->head;
last_node_->next = temp_node_->next;
}
}
free(temp_node_);
b_ret_ = true;
_node_num--;
break;
}
last_node_ = temp_node_;
temp_node_ = temp_node_->next;
}
双向链表的 查找
双向和单向的链表查找是一样的 只能一个节点一个节点的查找,不过不同的是,双向链表可以从后开始找,如果知道是顺序排好的,就可以从头或尾查找。比单向链表好一点。
代码如下:
list_node *temp_node_ = _head_node;
while (temp_node_ != nullptr)
{
if(temp_node_->count == count_paramter)
{
return temp_node_;
}
temp_node_ = temp_node_->next;
}
总结
简单来说双向链表和单向链表差距不大,就是查找太慢,但可以用其他方式解决。例如跳表。