• (C/C++学习)18.C语言双向链表


    说明:数组提供了连续内存空间的访问和使用,而链表是对内存零碎空间的有效组织和使用。链表又分为单向链表和双向链表,单向链表仅提供了链表的单方向访问,相比之下,双向链表则显得十分方便。


    一.单向链表的节点

    如下代码所示,双向链表的节点包含两个指向关系和一个数据空间,两个指向分别连接该节点的上一个和下一个节点,数据类型可以是一个结构体类型,也可以是其他类型。

      1 typedef struct node
      2 {
      3   int data;
      4   struct node *pre;
      5   struct node *next;
      6 }Node;



    二.双向链表的创建

    头插法和尾插法只看代码比较难以与理解,建议画出插入节点时的链表变化图则会非常容易理解,另外,个人认为头插法较优,因为其插入逻辑一步到位,不像尾插法还需在后面完成双向链表的环状连接。

    1.头插法

      1 Node * creatList()
      2 {
      3    Node * head = (Node*)malloc(sizeof(Node));
      4    Node * cur = NULL;
      5    head->next = head;
      6    head->pre = head;
      7    int data;
      8    scanf("%d",&data);
      9    while(data)
     10      {
     11        cur = (Node*)malloc(sizeof(Node));
     12        cur->data = data;
     13        cur->next = head->next;
     14        cur->pre = head;
     15        head->next = cur;
     16        cur->next->pre = cur;
     17        scanf("%d",&data);
     18      }
     19   return head;
     20 }


    2.尾插法

      1 Node * creatList()
      2 {
      3   Node * head = (Node*)malloc(sizeof(Node));
      4   Node * phead = head;
      5   Node * cur = NULL;
      6   phead->next = NULL;
      7   phead->pre = NULL;
      8   int data;
      9   scanf("%d",&data);
     10   while(data)
     11   {
     12      cur = (Node*)malloc(sizeof(Node));
     13      cur->data = data;
     14      phead->next = cur;
     15      cur->pre = phead;
     16      phead = cur;
     17      scanf("%d",&data);
     18   }
     19 //完成回环
     20   cur->next = head;
     21   head->pre = cur;
     22   return head;
     23 }



    三.双向链表的元素插入(头插法)

    插入方法:先让插入的节点有所指向,再考虑指向它的指针,具体插入如下:

      1 void insertList(Node * head)
      2 {
      3    printf("intsert new node:");
      4    int data;
      5    scanf("%d",&data);
      6    Node * cur;
      7    cur = (Node*)malloc(sizeof(Node));
      8    cur->data = data;
      9    cur->next = head->next;
     10    cur->pre = head;
     11    head->next = cur;
     12    cur->next->pre = cur;
     13 }



    四.双向链表的查找

    既然是双向链表,其查找方式也应该是是双向查找,比起单向链表的单向查找,双向查找同时从两个方向进行查找,加快了查找的速度。

      1 Node * searchList(Node * head,int find)
      2 {
      3    Node * pClock = head->next;
      4    Node * pAntiClock = head->pre;
      5    while (pAntiClock != pClock->pre)
      6    {
      7        if(pClock->data == find)
      8        return pClock;
      9        if(pAntiClock->data == find)
     10        return pAntiClock;
     11        if(pClock == pAntiClock)
     12        return NULL;
     13        pClock = pClock->next;
     14        pAntiClock = pAntiClock->pre;
     15 }
     16    return NULL;
     17 }



    五.删除某个节点

      1 void deleteList(Node * pfind)
      2 {
      3    if(pfind == NULL)
      4    return;
      5    else
      6     {
      7       pfind->pre->next = pfind->next;
      8       pfind->next->pre = pfind->pre;
      9       free(pfind);
     10     }
     11 }



    六.链表排序(按值排序)

      1 void sortList(Node * head,int n)
      2 {
      3     Node * p,*q;
      4     for(int i=0; i<n-1; i++)
      5     {
      6       p = head->next;
      7       q = p->next;
      8       for(int j=0; j<n-1-i; j++)
      9       {
     10         if(p->data > q->data)
     11         {
     12           p->data = p->data ^ q->data;
     13           q->data = p->data ^ q->data;
     14           p->data = p->data ^ q->data;
     15         }
     16       p = p->next;
     17       q = q->next;
     18       }
     19     }
     20 }



    七.链表的销毁

      1 void destroyList(Node * head)
      2 {
      3    head->pre->next = NULL;
      4    Node * pre = head;
      5    while(head != NULL)
      6    {
      7      head = head->next;
      8      free(pre);
      9      pre = head;
     10    }
     11 }


    说明:链表的操作还有如求长度、打印以及交换指针排序等,由于相对较为简单,此处就不再例举。重要提醒:链表的某些操作较难理解,最好画图加以辅助理解。

  • 相关阅读:
    UE4智能指针:TUniquePtr
    浅析UE4垃圾回收
    UE4中资源的引用
    ELF文件基础
    【JVM】JVM和Java 体系架构
    【Java多线程】Java线程生命周期、线程同步、线程通信(二)
    【Java多线程】Java多线程基础(一)
    【Java面试题】MySQL索引底层为什么用到B+树
    【算法】B树、B+树详解
    【Kafka】 Kafka的简介与架构(三)
  • 原文地址:https://www.cnblogs.com/tuihou/p/10004441.html
Copyright © 2020-2023  润新知