【双链表增删查改接口的实现】

简介: 【双链表增删查改接口的实现】

1 初始化链表

ListNode* ListNodeCreat(LTDataType x)
{
  ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
  if (newnode)
  {
    newnode->data = x;
    newnode->next = NULL;
    newnode->prev = NULL;
  }
  return newnode;
}
ListNode* InitList(void)
{
  ListNode* phead = ListNodeCreat(1);
  phead->next = phead;
  phead->prev = phead;
  return phead;
}

链表的初始化我们将phead的prev与next都指向phead,这里的处理在后面有一些妙用,这里就先不说了,头结点这里是通过返回值实现的,当然,通过二级指针也可以,效果都差不多。头结点是不存储数据的,只是充当哨兵的作用。

2 尾插和头插

尾插的具体代码:

void ListPushBack(ListNode* phead, LTDataType x)
{
  assert(phead);
  ListNode* tail = phead->prev;
  ListNode* newtail = ListNodeCreat(x);
  tail->next = newtail;
  newtail->prev = tail;
  newtail->next = phead;
  phead->prev = newtail;
  //ListInsert(phead, x);
}

尾插的实现很简单,都能够看懂。在这里我们就可以看见将phead的prev与next都指向phead的好处了,就算phead后面一个结点都没有依然能够处理,这样写代码就很简练了。

头插的具体代码:

void ListPushFront(ListNode* phead, LTDataType x)
{
  assert(phead);
  ListNode* next = phead->next;
  ListNode* newnode = ListNodeCreat(x);
  phead->next = newnode;
  newnode->prev = phead;
  newnode->next = next;
  next->prev = newnode;
  //ListInsert(phead->next, x);
}

头插的实现也比较简单,其实把图画好就能够解决问题,这里当头结点后面一个结点都没有也能够处理。

来看看效果:


c9c80d941d854cd3a19a8520e82b4e04.png

3 尾删和头删

尾删和头删对于双链表来说也比较简单,这里就放在一起写了:

void ListPopBack(ListNode* phead)
{
  assert(phead);
  ListNode* tail = phead->prev;
  ListNode* prev = tail->prev;
  prev->next = phead;
  phead->prev = prev;
  free(tail);
  //ListErase(phead->prev);
}
void ListPopFront(ListNode* phead)
{
  assert(phead);
  ListNode* next = phead->next->next;
  free(phead->next);
  phead->next = next;
  next->prev = phead;
  //ListErase(phead->next);
}

按部就班的写,注意不要写漏了就ok了。

效果:abb8f8e714c2426eb15b4927d5cda36a.png


4 查找和查插和查删)


查找的具体代码:

ListNode* ListFind(ListNode* phead, LTDataType x)
{
  assert(phead);
  ListNode* cur = phead->next;
  while (cur != phead)
  {
    if (cur->data == x)
    {
      return cur;
    }
    else
    {
      cur = cur->next;
    }
  }
  return NULL;
}

与单链表一样,这个也可以改变数据:

03276fe8cdc8427f831cabe865855482.png

查插的具体代码:

void ListInsert(ListNode* pos, LTDataType x)
{
  assert(pos);
  ListNode* prev = pos->prev;
  ListNode* newnode = ListNodeCreat(x);
  prev->next = newnode;
  newnode->prev = prev;
  newnode->next = pos;
  pos->prev = newnode;
}

这里是在pos位前面插入数据,实现起来也比较简单。

查删的具体代码:

void ListErase(ListNode* pos)
{
  assert(pos);
  ListNode* prev = pos->prev;
  ListNode* next = pos->next;
  prev->next = next;
  next->prev = prev;
  free(pos);
}

有了查删和查插后我们不难发现,头插和尾插都可以用查插实现,头删和尾删都可以用查删实现。

头插在 phead->next前插入,尾插在phead前插入,头删位置为phead->next,尾删位置为phead->prev.

在上面实现代码的时候注释掉的就是这种方法。

5 释放

void ListDestroy(ListNode* phead)
{
  ListNode* cur = phead;
  ListNode* next = phead->next;
  while (cur->next!=phead)
  {
    free(cur);
    cur = next;
    next = next->next;
  }
}

释放链表与单链表差不多,比较容易理解。

好了,今天的分享就到这里了,如果该文对你有帮助的话能不能3连支持一下博主呢?


d1feff5286c941c0bd431460f56c4563.gif


目录
相关文章
|
3月前
|
存储 算法 Java
【数据结构与算法】4.自主实现单链表的增删查改
【数据结构与算法】4.自主实现单链表的增删查改
|
9月前
|
存储
单链表————单链表的构建,增删查改功能的实现
单链表————单链表的构建,增删查改功能的实现
不带头非循环的单向链表的增删查改的实现(代码版)
不带头非循环的单向链表的增删查改的实现(代码版)
|
5月前
|
算法 DataX
【数据结构】双向链表的增删查改(C 代码实现)
【数据结构】双向链表的增删查改(C 代码实现)
43 0
|
9月前
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能(2)
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能(2)
46 0
|
9月前
|
存储
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能
91 0
|
11月前
|
C语言
带头双向循环链表增删查改实现(C语言)
带头双向循环链表增删查改实现(C语言)
|
11月前
双向带头循环链表(增删查改)
双向带头循环链表(增删查改)
|
12月前
|
存储
【数据结构】带头+双向+循环链表增删查改实现
【数据结构】带头+双向+循环链表增删查改实现