C语言链表结构(3)——双链表的增删改查

双向链表的增删改查

一.双向链表和单向链表的区别

1. 双向链表的特征是什么?
单向链表节点里只有一个后继指针next,所以单向链表只能往后指。
双向链表节点里不仅仅有后继指针next,而是有前驱指针prev,双向链表既可以往前访问节点,也可以往后访问节点。

2. 双向链表模型?
struct list_node{
    /* 数据域 */
    ....;

    /* 指针域 */
    前驱指针...;
    后继指针...;
};

二. 双向链表的增删改查?
1. 初始化链表?
struct list_node *init_list_head(struct list_node *head)
{
  head = (struct list_node *)malloc(sizeof(struct list_node));
  if(head == NULL)
    printf("malloc head error!\n");

  head->prev = NULL;
  head->next = NULL;

  return head;
}

2. 尾插链表?
int tail_add_list(struct list_node *head,int num)
{
  struct list_node *Node = NULL;
  Node = (struct list_node *)malloc(sizeof(struct list_node));
  if(Node == NULL)
    printf("malloc Node error!\n");

  Node->a = num;

  struct list_node *p = NULL;
  for(p=head;p->next!=NULL;p=p->next);

  p->next = Node;
  Node->next = NULL;
  Node->prev = p;

  return 0;
}

3. 头插数据?
int head_add_list(struct list_node *head,int num)
{
  struct list_node *Node = NULL;
  Node = (struct list_node *)malloc(sizeof(struct list_node));
  if(Node == NULL)
    printf("malloc Node error!\n");

  Node->a = num;

  Node->next = head->next;

  if(head->next != NULL)
    head->next->prev = Node;

  head->next = Node;
  Node->prev = head;

  return 0;
}

4. 遍历链表?
int backward_show_list(struct list_node *head)   //向前遍历
{
  struct list_node *p = NULL;
  for(p=head;p->next!=NULL;p=p->next); //从循环中出来时,p就指向最后一个节点

  for(;p!=head;p=p->prev)
  {
    printf("p->a:%d\n",p->a);
  }

  return 0;
}

int forward_show_list(struct list_node *head)     //向后遍历
{
  struct list_node *p = NULL;
  for(p=head->next;p!=NULL;p=p->next)
  {
    printf("p->a:%d\n",p->a);
  }

  return 0;
}

5. 搜索节点?
int search_list_node(struct list_node *head,int num)
{
  struct list_node *p = NULL;
  for(p=head->next;p!=NULL;p=p->next)
  {
    if(p->a == num)
    {
      printf("p->a:%d\n",p->a);
    }
  }

  return 0;
}

6. 删除节点?
int delete_list_node(struct list_node *head,int num)
{
  struct list_node *p = NULL;
  struct list_node *q = NULL;

  for(q=head,p=head->next;p!=NULL;q=p,p=p->next)
  {
    if(p->a == num)
    {
      q->next = p->next;
      if(p->next!=NULL) //说明删除的不是最后一个
        p->next->prev = q;

      free(p);
    }
  }

  return 0;
}

7. 删除链表?
int delete_list(struct list_node *head)
{
  struct list_node *p = NULL;
  struct list_node *q = NULL;

  for(p=q=head;p!=NULL;p=q)
  {
    q = p->next;
    free(p);
  }

  return 0;
}

双向循环链表和双向链表差不多,主要是把最后一个节点的后继指向头结点,将头结点的前驱指向最后一个节点,至于增删改查的区别按照逻辑修改源码(例如遍历是将p!=NULL改为p!=head)等

posted @ 2019-11-06 10:10  水镜·八咫  阅读(697)  评论(0)    收藏  举报