• 单向循环链表


    注意:

               在插入和删除的操作中,一定要把链表的头和尾拿出来单独分析!  由于链表在第一次完整连接后(比如下面程序中的PushBack函数)每个节点在链表中的内存地址已经固定了下来,比如上图中,b里保存的指针始终就是指向c的next的地址,c中保存的指针始终就是指向d的next的地址,d中保存的指针始终是指向head的地址,所以即使在a,b间插入一个元素e,也不会影响b,c,d节点指针的指向。所以只要不是有关处理头尾元素的操作,都不需要从头到尾地把链表重新连接一遍!因为位置在第一次连接的时候就已经固定了!

     1 //CircleList.h
     2 
     3 #pragma once
     4 
     5 #include <stdio.h>
     6 #include <stdlib.h>
     7 
     8 typedef struct Node
     9 {
    10     int element;
    11     Node *next;
    12 }Node;
    13 
    14 typedef struct CircleList    //单向循环链表
    15 {
    16     Node *head;
    17     int length;
    18 }CircleList;
    19 
    20 void InitList(CircleList *cir);    //创建循环链表
    21 
    22 Node* GetPrev(CircleList *cir, Node* q);  //获取节点q前驱元素的指针
    23 
    24 Node* GetBack(CircleList *cir, Node* q);  //获取节点q后继元素的指针
    25 
    26 Node* BackElem(CircleList *cir);  //返回指向尾节点的指针
    27 
    28 void PushBack(CircleList *cir, int elem);  //向链表尾部添加元素
    29 
    30 void InsertElem(CircleList *cir, int position, int elem); //在position的前一个位置处插入元素
    31 
    32 void DeleteElem(CircleList *cir, int position);  //删除position位置处的元素
    33 
    34 void ClearList(CircleList *cir);   //清空循环链表
    35 
    36 void PrintListFromFirst(CircleList *cir);   //从第一个元素开始遍历循环链表
    37 
    38 void PrintListFromPosition(CircleList *cir, int position);  //从第position处的元素开始循环遍历整个链表
      1 //CircleList.c
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include "CircleList.h"
      6 
      7 void InitList(CircleList *cir)    //创建循环链表
      8 {
      9     cir->length = 0;
     10     cir->head = (Node*)malloc(sizeof(Node));
     11     cir->head->next = NULL;
     12 }
     13 
     14 Node* GetPrev(CircleList *cir, Node* q)  //获取节点q前驱元素的指针
     15 {
     16     if (cir->head->next == q)
     17     {
     18         printf("该节点没有前驱元素!
    ");
     19         return NULL;
     20     }
     21     Node *p = cir->head;
     22     for (int i = 1; i <= cir->length; ++i)
     23     {
     24         p = p->next;
     25         if (p->next == q)
     26             return p;
     27     }
     28 }
     29 
     30 Node* GetBack(CircleList *cir, Node* q)  //获取节点q后继元素的指针
     31 {
     32     if (q == BackElem(cir))
     33     {
     34         printf("该节点没有后继元素!
    ");
     35         return NULL;
     36     }
     37     Node *p = cir->head;
     38     for (int i = 1; i <= cir->length; ++i)
     39     {
     40         p = p->next;
     41         if (q->next == p)
     42             return p;
     43     }
     44 }
     45 
     46 Node* BackElem(CircleList *cir)  //返回指向尾节点的指针
     47 {
     48     Node *p = cir->head;
     49     if (cir->length == 0)
     50         return p;
     51     for (int i = 1; i <= cir->length; ++i)
     52         p = p->next;
     53     return p;
     54 }
     55 
     56 void PushBack(CircleList *cir, int elem)   //向链表尾部添加元素
     57 {
     58     Node *NewNode = (Node*)malloc(sizeof(Node));
     59     NewNode->element = elem;
     60     Node *p = BackElem(cir);
     61     p->next = NewNode;
     62     NewNode->next = cir->head->next;
     63     ++cir->length;
     64 }
     65 
     66 void InsertElem(CircleList *cir, int position, int elem) //在position的前一个位置处插入元素(head的position为0)
     67 {
     68     if (position > cir->length + 1 || position < 1)
     69     {
     70         printf("插入失败!请在合理的范围内插入元素!
    ");
     71         return;
     72     }
     73     if (position == cir->length + 1 || position == 1)
     74     {
     75         Node *q = BackElem(cir);
     76         Node *NewNode = (Node*)malloc(sizeof(Node));
     77         NewNode->element = elem;
     78         q->next = NewNode;
     79         NewNode->next = cir->head->next;
     80         if (position == 1)
     81             cir->head->next = NewNode;
     82         ++cir->length;
     83         return;
     84     }
     85     Node *p = cir->head;
     86     for (int i = 1; i <= position - 1; ++i)
     87         p = p->next;   //获取position前一个位置处的指针p
     88     Node *NewNode = (Node*)malloc(sizeof(Node));
     89     NewNode->element = elem;
     90     NewNode->next = p->next;
     91     p->next = NewNode;
     92     ++cir->length;
     93     return;
     94 }
     95 
     96 
     97 void DeleteElem(CircleList *cir, int position)  //删除position位置处的元素
     98 {
     99     Node *p = cir->head;
    100     if (position == 1)
    101     {
    102         p = p->next;
    103         cir->head->next = p->next;
    104         Node *q = BackElem(cir);
    105         q->next = p->next;
    106         free(p);
    107         --cir->length;
    108         return;
    109     }
    110     if (position == cir->length)
    111     {
    112         Node *q = BackElem(cir);
    113         Node *p = GetPrev(cir, q);         //令p指向倒数第二个元素
    114         p->next = cir->head->next;
    115         free(q);
    116         --cir->length;
    117         return;
    118     }
    119     for (int i = 1; i <= position - 1; ++i)
    120         p = p->next;   //获取position前一个位置处的指针p
    121     Node *q = p->next;
    122     p->next = q->next;
    123     free(q);
    124     --cir->length;
    125     return;
    126 }
    127 
    128 
    129 void ClearList(CircleList *cir)   //清空循环链表
    130 {
    131     int temp = cir->length;  //删除过程中cir->length时刻变化,所以应该先将其原始值保存下来
    132     for (int i = 1; i <= temp; ++i)
    133     {
    134         DeleteElem(cir, 1);        //删除temp次1号节点,即可把整个链表清空
    135     }                                //删除过程中length已经在一直自减,所以不需要添加额外的length自减语句
    136 }
    137 
    138 void PrintListFromFirst(CircleList *cir)   //从第一个元素开始遍历循环链表
    139 {
    140     Node *p = cir->head;
    141     for (int i = 1; i <= cir->length; ++i)
    142     {
    143         p = p->next;
    144         printf("%d  ", p->element);
    145     }
    146 }
    147 
    148 void PrintListFromPosition(CircleList *cir, int position)  //从第position处的元素开始循环遍历整个链表
    149 {
    150     Node *p = cir->head;
    151     for (int i = 1; i <= position; ++i)
    152         p = p->next;   //获取position位置处的指针p
    153 
    154     Node *org = p;     //用org记录p的原始位置,用于作为循环遍历的终止条件
    155     do
    156     {
    157         printf("%d ", p->element);
    158         p = p->next;
    159     } while (p != org);
    160 }
     1 //main.c
     2 
     3 #include <stdio.h>
     4 #include <stdlib.h>
     5 #include "CircleList.h"
     6 
     7 int main()
     8 {
     9     CircleList cir;
    10     InitList(&cir);
    11     PushBack(&cir, 1);
    12     PushBack(&cir, 2);
    13     PushBack(&cir, 3);
    14     PushBack(&cir, 4);
    15     PushBack(&cir, 5);
    16     PushBack(&cir, 6);
    17     PushBack(&cir, 7);
    18     PushBack(&cir, 8);
    19     InsertElem(&cir,5,777);
    20 
    21 //  ClearList(&cir);
    22 //  InsertElem(&cir, 5, 666);
    23 //  DeleteElem(&cir,8);
    24     Node *p = cir.head -> next;
    25 //  Node* p =BackElem(&cir);
    26     printf("%d
    ", p->element);
    27     Node *q = GetBack(&cir, p);
    28     printf("%d
    ", q->element);
    29     Node *q2 = GetPrev(&cir, q);
    30     printf("%d
    ", q2->element);
    31 //  DeleteElem(&cir,7);
    32 //  PrintListFromFirst(&cir);
    33 //  PrintListFromPosition(&cir,8);
    34 //  printf("%d", cir.length);
    35 
    36     return 0;
    37 }
  • 相关阅读:
    bzoj3064: Tyvj 1518 CPU监控
    bzoj3272: Zgg吃东西&&3267: KC采花
    bzoj2759: 一个动态树好题
    bzoj4594: [Shoi2015]零件组装机
    bzoj4873: [Shoi2017]寿司餐厅
    bzoj4593: [Shoi2015]聚变反应炉
    codeforces 739E
    bzoj2034: [2009国家集训队]最大收益
    mybatis-generator使用心得
    Linux 各种软件的安装-Jenkins和svn结合
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/9406767.html
Copyright © 2020-2023  润新知