线性表--顺序表--双向链表(六)

时间:2022-07-28
本文章向大家介绍线性表--顺序表--双向链表(六),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

双向链表图示

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

1.定义链表

typedef struct Node
{
 int data;
 struct Node * prior;
 struct Node * next;
}Node;

2.初始化头尾结点

Node * InitListHead()
{
 Node * Head = (Node *)malloc(sizeof(Node));
 Head->data = 0;
 Head->next = NULL;
 Head->prior = NULL;
 return Head;
}
Node * InitListEnd()
{
 Node * End = (Node *)malloc(sizeof(Node));
 End->data = 0;
 End->next = NULL;
 End->prior = NULL;
 return End;
}

3.初始化链表结点

void CreateCLinkList(Node ** Head,Node ** End,int a)//创建节点
{
 //尾插法 
 Node * P = (Node *)malloc(sizeof(Node));
 P->data = a;
 if ((*Head)->next == NULL)
 {
  (*Head)->next = P;
  P->prior = (*Head);
 }
 else
 {
  (*End)->prior->next = P;
  P->prior = (*End)->prior;
 }
 P->next = (*End);
 (*End)->prior = P;
 (*Head)->data++;
}

4.插入操作

(1)图示

(2)代码

int InsertList(Node ** Head, Node ** End,int i,int num)//i为插入位置
{
 //我们可以在头结点的数据存储链表长度,来判断插入位置是否合法,这里假定输入的i合法
 //因为有首尾链表,我们可还以判断输入位置在前半部分,还是后半部分,从而选择使用头节点还是尾节点,这里就不做示范了
 j = 0;
 Node *Phead = (*Head);
 Node *Pend = (*End);
 Node * P = (Node *)malloc(sizeof(Node));
 P->data = num;
 if (i > (*Head)->data)
  return 0;
 //正向操作
 //while (Phead != NULL)
 //{
 // if (i == j+1)
 // {
 //  Phead->next->prior = P;
 //  P->next = Phead->next;
 //  Phead->next = P;
 //  P->prior = Phead;
 //  (*Head)->data++;
 // }
 // Phead = Phead->next;
 // j++;
 //}
 //这不是我们今天的重点 今天的重点是 双向链表的逆向操作:
  while (Pend->prior != NULL)
 {
  if (Phead->data - i == j)
  {
   P->prior = Pend->prior;
   Pend->prior->next = P;
   P->next = Pend;
   Pend->prior = P;
   (*Head)->data++;
   return 0;
  }
  Pend = Pend->prior;
  j++;
 }
 return 0;
}

5.遍历操作

void printList(Node * Head, Node * End)
{
 //双向链表的遍历条件是头指针是否等于尾节点,或者是指针是否为空
 Node * Phead = Head->next;
 Node * Pend = End->prior;

 //正向操作
 //while (Phead->next != NULL)
 //{
 // printf("第一种 %dn", Phead->data);
 // Phead = Phead->next;
 //}
 //printf("n");
 //Node * Phead_1 = Head->next;
 //while (Phead_1 != Pend)
 //{
 // printf("第二种 %dn", Phead_1->data);
 // Phead_1 = Phead_1->next;
 //}
 //同样这也是正向操作,下面来看逆向操作
  while (Pend->prior != NULL)
 {
  printf("第一种 %dn", Pend->data);
  Pend = Pend->prior;
 }
 printf("n");
}

6.删除操作

int DelList(Node ** Head, Node ** End, int i)
{
 j = 0;
 Node *Phead = (*Head);
 Node *Pend = (*End);
 Node * P = NULL;
 if (i > (*Head)->data)
  return 0;

 //正向操作
 //while (Phead->next != NULL)
 //{
 // if (i == j + 1)
 // {
 //  P = Phead->next;
 //  Phead->next = Phead->next->next;
 //  Phead->next->prior = Phead;
 //  P->next = NULL;
 //  P->prior = NULL;
 //  free(P);
 //  (*Head)->data--;
 // }
 // Phead = Phead->next;
 // j++;
 //}
 //同样,我们来看逆向操作:
  while (Pend->prior != NULL)
 {
  if (Phead->data - i == j+1 )
  {
   P = Pend->prior;
   Pend->prior->next = Pend;
   Pend->prior = Pend->prior->prior;
   P->next = NULL;
   P->prior = NULL;
   free(P);
   (*Head)->data--;
  }
  Pend = Pend->prior;
  j++;
 }
 return 0;
}

7.int main()操作

int main()
{
int j=0;
 Node * Head = InitListHead();
 Node * End = InitListEnd();
 Node ** PH = &Head;
 Node ** PE = &End;
 for (int i = 1; i <= 10; i++)
 {
  CreateCLinkList(PH, PE, i);
 }
 printList(Head, End);
 InsertList(PH, PE, 3, 99);
 printList(Head, End);
 DelList(PH, PE, 3);
 printList(Head, End);
 return 0;
}

8.切记申请的内存记得要释放哦!!!

若有错误。欢迎批评指出,欢迎交流。 每文一句:生命中,不断地有人离开或进入。于是,看见的,看不见了;记住的,以往了。生命中,不断地有得到或失落。于是看不见的,看见了;以往的,记住了,然而,看不见的,是不是就等于不存在?记住的,永远不会消失?