[数据结构]#3 循环链表/双向链表

循环链表

简单的来说,就是将原来单链表中最有一个元素的next指针指向第一个元素或头结点,链表就成了一个环,头尾相连,就成了循环链表------circultlar linker list。

注意非空表,和空表。多数会加入头结点。

原来结束的条件是:

p->next != NULL ------> p-next != Head

我们再结合单向链表的结构,则可得到更加实用的双向链表------double link list。

其基本框架的搭建:

cpp 复制代码
#include "DouLink.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//创建双向链表
DouLinkList *CreateDouLinkList()
{
  DouLinkList *dl = malloc(sizeof(DouLinkList));
  if (NULL == dl)
  {
    fprintf(stderr, "CreateDouLinkList malloc\n");
    return NULL;
  }
  dl->head = NULL;
  dl->clen = 0;
  return dl;
}

//检查是否为空
int IsEmpytDouLinkList(DouLinkList *dl)
{
  return 0 == dl->clen;
}

//打印
int ShowDouLinkList(DouLinkList *dl, SHOW_DIR dir)
{
  int size = GetSizeDouLinkList(dl);
  DouLinkNode *tmp = dl->head;
  if (DIR_FORWARD == dir)
  {
    for (int i = 0; i < size; i++)
    {
      printf("name:%s sex:%c age:%d score:%d\n", tmp->data.name, tmp->data.sex,
             tmp->data.age, tmp->data.score);
      tmp = tmp->next;
    }
  }
  else
  {
    while (tmp->next)
    {
      tmp = tmp->next;
    }
    for (int i = 0; i < size; i++)
    {
      printf("name:%s sex:%c age:%d score:%d\n", tmp->data.name, tmp->data.sex,
             tmp->data.age, tmp->data.score);
      tmp = tmp->prev;
    }
  }
}

//有效元素个数
int GetSizeDouLinkList(DouLinkList *dl)
{
  return dl->clen;
}

//释放内存
int DestroyDouLinkList(DouLinkList *dl)
{
  DouLinkNode *tmp = dl->head;
  int size = GetSizeDouLinkList(dl);
  for (int i = 0; i < size; i++)
  {
    tmp = dl->head;
    dl->head = dl->head->next;
    free(tmp);
  }
  free(dl);
  return 0;
}

然后是双向链表的操作(增、删、改、查):

cpp 复制代码
//头插
int InsertHeadDouLinkList(DouLinkList *dl, DATATYPE *data)
{
  DouLinkNode *newnode = malloc(sizeof(DouLinkNode));
  if (NULL == newnode)
  {
    fprintf(stderr, "InsertHeadDouLinkList malloc\n");
    return 1;
  }

  memcpy(&newnode->data, data, sizeof(DATATYPE));
  newnode->next = NULL;
  newnode->prev = NULL;
  if (IsEmpytDouLinkList(dl))
  {
    dl->head = newnode;
  }
  else
  {
    newnode->next = dl->head;
    dl->head->prev = newnode;
    dl->head = newnode;
  }

  dl->clen++;
  return 0;
}

//尾插
int InsertTailDouLinkList(DouLinkList *dl, DATATYPE *data)
{
  if (IsEmpytDouLinkList(dl))
  {
    return InsertHeadDouLinkList(dl, data);
  }
  DouLinkNode *newnode = malloc(sizeof(DouLinkNode));
  if (NULL == newnode)
  {
    fprintf(stderr, "InsertTailDouLinkList malloc\n");
    return 1;
  }

  memcpy(&newnode->data, data, sizeof(DATATYPE));
  newnode->next = NULL;
  newnode->prev = NULL;

  DouLinkNode *tmp = dl->head;
  while (tmp->next)
  {
    tmp = tmp->next;
  }
  // init_node
  newnode->prev = tmp;
  tmp->next = newnode;
  dl->clen++;
  return 0;
}

//按位置插入
int InsertPosDouLinkList(DouLinkList *dl, DATATYPE *data, int pos)
{
  int size = GetSizeDouLinkList(dl);
  if (pos < 0 || pos > size)
  {
    return 1;
  }

  if (0 == pos)  // head
  {
    return InsertHeadDouLinkList(dl, data);
  }
  else if (pos == size)  // tail
  {
    return InsertTailDouLinkList(dl, data);
  }
  else  // mid
  {
    DouLinkNode *tmp = dl->head;
    for (int i = 0; i < pos - 1; i++)
    {
      tmp = tmp->next;
    }
    // tmp at end node
    // init_node; malloc ,NULL,NULL
    DouLinkNode *newnode = malloc(sizeof(DouLinkNode));
    if (NULL == newnode)
    {
      fprintf(stderr, "InsertTailDouLinkList malloc\n");
      return 1;
    }
    memcpy(&newnode->data, data, sizeof(DATATYPE));
    newnode->next = NULL;
    newnode->prev = NULL;

    newnode->next = tmp->next;
    newnode->prev = tmp;
    newnode->next->prev = newnode;
    tmp->next = newnode;

    dl->clen++;
  }
  return 0;
}



//删除
int DeleteDouLinkList(DouLinkList *dl, char *name)
{
  DouLinkNode *tmp = FindDouLinkList(dl, name);
  if (NULL == tmp)
  {
    printf("DeleteDouLinkList error\n");
    return 1;
  }
  if (tmp == dl->head)
  {
    dl->head = dl->head->next;
    if (dl->head->prev)
    {
      dl->head->prev = NULL;
    }
  }
  else  // mid end
  {
    if (tmp->next)
    {
      tmp->next->prev = tmp->prev;
    }
    tmp->prev->next = tmp->next;
  }

  free(tmp);
  dl->clen--;
  return 0;
}


//修改
int ModifyDouLinkList(DouLinkList *dl, char *name, DATATYPE *data)
{
  DouLinkNode *tmp = FindDouLinkList(dl, name);
  if (NULL == tmp)
  {
    printf("modify failure...\n");
    return 1;
  }

  memcpy(&tmp->data, data, sizeof(DATATYPE));
  return 0;
}

//查找
DouLinkNode *FindDouLinkList(DouLinkList *dl, char *name)
{
  DouLinkNode *tmp = dl->head;
  while (tmp)
  {
    if (0 == strcmp(tmp->data.name, name))
    {
      return tmp;
    }
    tmp = tmp->next;
  }
  return NULL;
}