• C/C++语言实现单链表(带头结点)


    彻底理解链表中为何使用二级指针或者一级指针的引用

    数据结构之链表-链表实现及常用操作(C++篇)

      C语言实现单链表,主要功能为空链表创建,链表初始化(头插法),链表元素读取,按位置插入,(有序链表)按值插入,按位置删除,按值删除,清空链表,销毁链表。

      关键思路:(1)将结点创建结构体;(2)链表中添加头结点,以便统一操作;(3)使用结点一级指针和二级指针的异同点;(4)链表的最小操作单位是结点;(5)操作的起始位置是头结点还是第一个结点,及起始索引是0还是1. 

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <time.h>
      4 
      5 //涉及到结构体自引用
      6 typedef struct Node{
      7     int data;
      8     struct Node *next;
      9 }Node;
     10 
     11 //创建空链表
     12 //必须用二级指针,涉及到头指针的创建
     13 int iniList(Node **List){
     14     *List = (Node *)malloc(sizeof(Node));
     15     if (NULL == *List){
     16         return 0;
     17     }
     18 
     19     (*List)->next = NULL; //创建头结点
     20     return 1;
     21 }
     22 
     23 //初始化链表(头插法)
     24 //必须二级指针
     25 int iniListHead(Node **List, int n){
     26     *List = (Node *)malloc(sizeof(Node));
     27     if (NULL == *List){
     28         return 0;
     29     }
     30     (*List)->next = NULL;
     31     srand(time(0));
     32 
     33     int i = 0;
     34     while (i < n){
     35         Node *tmpNode = (Node *)malloc(sizeof(Node));
     36         if (NULL == tmpNode){
     37             return 0;
     38         }
     39         tmpNode->data = rand() % 100 + 1;
     40         tmpNode->next = (*List)->next;
     41         (*List)->next = tmpNode;
     42         
     43 
     44         ++i;
     45     }
     46     return 1;
     47 }
     48 
     49 //初始化链表(尾插法)
     50 //必须二级指针
     51 //需要借助辅助变量pCurrent,将每次尾插的新元素当做当前元素
     52 int iniListTail(Node **List, int n){
     53     *List = (Node *)malloc(sizeof(Node));
     54     if (NULL == *List){
     55         return 0;
     56     }
     57     (*List)->next = NULL;
     58     srand(time(0));
     59 
     60     Node *pCurrent = *List;
     61 
     62     int i = 0;
     63     while (i < n){
     64         Node *tmpNode = (Node *)malloc(sizeof(Node));
     65         if (NULL == tmpNode){
     66             return 0;
     67         }
     68         tmpNode->data = rand() % 100 + 1;
     69         tmpNode->next = NULL;
     70         pCurrent->next = tmpNode;
     71         pCurrent = tmpNode;
     72 
     73         ++i;
     74     }
     75     return 1;
     76 }
     77 
     78 //清空链表(不删除头结点)
     79 //一级,二级指针均可
     80 //首先找到链表地址,然后移动至表尾
     81 //判断条件为指针域是否为空,即到达结尾
     82 int deleteList(Node *List){
     83 
     84     //这种方法无法删除尾结点
     85     //Node *p= List;
     86     //Node *q = NULL;
     87     //
     88     //while (p->next){
     89     //    q = p;
     90     //    free(p);
     91     //    p = q->next;
     92     //}
     93 
     94     Node *p = List->next;
     95     Node *q = NULL;
     96 
     97     while (p){
     98         q = p->next;
     99         free(p);
    100         p = q;
    101     }
    102 
    103     List->next = NULL;
    104     return 1;
    105 }
    106 
    107 //销毁链表
    108 //必须使用二级指针,销毁头结点和头指针
    109 //最后将链表头指针置空
    110 int desrotyList(Node **List){
    111 
    112     Node *p = *List;
    113     Node *q = NULL;
    114 
    115     //如果为空链表,直接删除头结点
    116     //如果不是空链表,从头结点开始删除
    117     while (p){
    118         q = p->next;
    119         free(p);
    120         p = q;
    121     }
    122     (*List) = NULL;
    123 
    124     //下面是从第一个结点开始删除
    125     //最后释放掉头结点
    126     //Node *p = (*List)->next;
    127     //Node *q = NULL;
    128     //
    129     //while (p){
    130     //    q = p->next;
    131     //    free(p);
    132     //    p = q;
    133     //}
    134     //free(*List);
    135     //(*List) = NULL;
    136 
    137     return 1;
    138 }
    139 
    140 //链表获取元素
    141 //一级,二级指针均可
    142 //头结点无意义,从第一个结点开始遍历,i从1开始
    143 //每次都指向下一结点,到pos-1即可
    144 int getList(Node *List, int pos, int *element){
    145     Node *p = List->next;
    146     
    147     int i = 1;
    148     while (p && i < pos){
    149         p = p->next;
    150         ++i;
    151     }
    152     *element = p->data;
    153     return 1;
    154 }
    155 
    156 //链表按位置插入
    157 //一级,二级指针均可
    158 //从头结点开始,有可能插入在第一个位置,遍历从1开始
    159 int insertListPos(Node *List, int pos, int value){
    160     Node *p = List;
    161 
    162     int i = 1;
    163     while (p && i < pos){
    164         p = p->next;
    165         ++i;
    166     }
    167     Node *tmpNode = (Node *)malloc(sizeof(Node));
    168     tmpNode->data = value;
    169     tmpNode->next = p->next;
    170     p->next = tmpNode;
    171     return 1;
    172 }
    173 
    174 //有序链表,按值插入
    175 //一二级指针均可
    176 int insertListValue(Node *List, int value){
    177     Node *pCur = List->next;
    178     Node *pPer = List;
    179     while (pCur && pCur->data < value){
    180         pPer = pCur;
    181         pCur = pCur->next;
    182     }
    183 
    184     Node *tmpNode = (Node *)malloc(sizeof(Node));
    185     if (NULL == tmpNode){
    186         return 0;
    187     }
    188     tmpNode->data = value;
    189     tmpNode->next = pPer->next;
    190     pPer->next = tmpNode;
    191     return 1;
    192 }
    193 
    194 //链表按位置删除
    195 //一二级指针均可
    196 //记得释放结点内存
    197 //如果删除第一个结点,需要操纵头结点
    198 int deleteListPos(Node *List, int pos){
    199     Node *p = List;
    200 
    201     int i = 1;
    202     while (p && i < pos){
    203         p = p->next;
    204         ++i;
    205     }
    206     if (NULL == p->next)
    207         return 0;
    208 
    209     Node *tmpNode = p->next;
    210     p->next = p->next->next;
    211     
    212     free(tmpNode);
    213     return 1;
    214 }
    215 
    216 //链表按值删除元素
    217 //一二级指针均可
    218 //从第一个结点开始
    219 int deleteListValue(Node *List, int value){
    220     Node *pCur = List->next;
    221     Node *pPer = List;
    222 
    223     while (pCur && pCur->data != value){
    224         pPer = pCur;
    225         pCur = pCur->next;
    226     }
    227     if (pCur == NULL){ //空链表不删除任何结点
    228         return 0;
    229     }
    230     else{
    231         pPer->next = pCur->next;
    232         free(pCur);
    233     }
    234     return 1;
    235 }
    236 
    237 int main(){
    238 
    239     Node *testList = NULL;
    240     iniList(&testList);
    241     //iniListHead(&testList, 3);
    242     //iniListTail(&testList, 3);
    243     
    244 
    245     insertListPos(testList, 1, 2);
    246     insertListPos(testList, 2, 4);
    247     insertListPos(testList, 3, 5);
    248     insertListPos(testList, 4, 10);
    249     //insertListPos(testList, 1, 1);
    250     insertListValue(testList, 1);
    251 
    252     //deleteListPos(testList, 1);
    253     //deleteListValue(testList, 4);
    254 
    255     //deleteList(testList);
    256 
    257     //printf("%d
    ", testList);
    258     //desrotyList(&testList);
    259     //printf("%d
    ", testList);
    260 
    261     Node * tmpNode = testList->next;
    262     while (tmpNode){
    263         printf("%d
    ", tmpNode->data);
    264         tmpNode = tmpNode->next;
    265     }
    266 
    267     printf("----------------------
    ");
    268 
    269     int a = 0;
    270     getList(testList, 2, &a);
    271     printf("%d
    ", a);
    272 
    273     system("pause");
    274 
    275     return 0;
    276 }
    C语言完整代码

      通过C++实现C语言的链表,主要区别:(1)struct可以不通过typedef,直接使用Node;(2)将malloc和free更换为new和delete

      1 #include<iostream>
      2 #include<ctime>
      3 
      4 using namespace std;
      5 
      6 struct Node{
      7     int data;
      8     Node *next;
      9 };
     10 
     11 //创建空链表
     12 //必须用二级指针,涉及到头指针的创建
     13 int iniList(Node **List){
     14     *List = new Node;
     15 
     16     (*List)->next = NULL; //创建头结点
     17     return 1;
     18 }
     19 
     20 //初始化链表(头插法)
     21 //必须二级指针
     22 int iniListHead(Node **List, int n){
     23     *List = new Node;
     24 
     25     (*List)->next = NULL;
     26     srand(time(0));
     27 
     28     int i = 0;
     29     while (i < n){
     30         Node *tmpNode = new Node;
     31 
     32         tmpNode->data = rand() % 100 + 1;
     33         tmpNode->next = (*List)->next;
     34         (*List)->next = tmpNode;
     35 
     36         ++i;
     37     }
     38     return 1;
     39 }
     40 
     41 //初始化链表(尾插法)
     42 //必须二级指针
     43 //需要借助辅助变量pCurrent,将每次尾插的新元素当做当前元素
     44 int iniListTail(Node **List, int n){
     45     *List = new Node;
     46 
     47     (*List)->next = NULL;
     48     srand(time(0));
     49 
     50     Node *pCurrent = *List;
     51 
     52     int i = 0;
     53     while (i < n){
     54         Node *tmpNode = new Node;
     55 
     56         tmpNode->data = rand() % 100 + 1;
     57         tmpNode->next = NULL;
     58         pCurrent->next = tmpNode;
     59         pCurrent = tmpNode;
     60 
     61         ++i;
     62     }
     63     return 1;
     64 }
     65 
     66 //清空链表(不删除头结点)
     67 //一级,二级指针均可
     68 //首先找到链表地址,然后移动至表尾
     69 //判断条件为指针域是否为空,即到达结尾
     70 int deleteList(Node *List){
     71 
     72     //这种方法无法删除尾结点
     73     //Node *p= List;
     74     //Node *q = NULL;
     75     //
     76     //while (p->next){
     77     //    q = p;
     78     //    free(p);
     79     //    p = q->next;
     80     //}
     81 
     82     Node *p = List->next;
     83     Node *q = NULL;
     84 
     85     while (p){
     86         q = p->next;
     87         delete p;
     88         p = q;
     89     }
     90 
     91     List->next = NULL;
     92     return 1;
     93 }
     94 
     95 //销毁链表
     96 //必须使用二级指针,销毁头结点和头指针
     97 //最后将链表头指针置空
     98 int desrotyList(Node **List){
     99 
    100     Node *p = *List;
    101     Node *q = NULL;
    102 
    103     //如果为空链表,直接删除头结点
    104     //如果不是空链表,从头结点开始删除
    105     while (p){
    106         q = p->next;
    107         delete p;
    108         p = q;
    109     }
    110     (*List) = NULL;
    111 
    112     //下面是从第一个结点开始删除
    113     //最后释放掉头结点
    114     //Node *p = (*List)->next;
    115     //Node *q = NULL;
    116     //
    117     //while (p){
    118     //    q = p->next;
    119     //    free(p);
    120     //    p = q;
    121     //}
    122     //free(*List);
    123     //(*List) = NULL;
    124 
    125     return 1;
    126 }
    127 
    128 //链表获取元素
    129 //一级,二级指针均可
    130 //头结点无意义,从第一个结点开始遍历,i从1开始
    131 //每次都指向下一结点,到pos-1即可
    132 int getList(Node *List, int pos, int *element){
    133     Node *p = List->next;
    134 
    135     int i = 1;
    136     while (p && i < pos){
    137         p = p->next;
    138         ++i;
    139     }
    140     *element = p->data;
    141     return 1;
    142 }
    143 
    144 //链表按位置插入
    145 //一级,二级指针均可
    146 //从头结点开始,有可能插入在第一个位置,遍历从1开始
    147 int insertListPos(Node *List, int pos, int value){
    148     Node *p = List;
    149 
    150     int i = 1;
    151     while (p && i < pos){
    152         p = p->next;
    153         ++i;
    154     }
    155     Node *tmpNode = new Node;
    156     tmpNode->data = value;
    157     tmpNode->next = p->next;
    158     p->next = tmpNode;
    159     return 1;
    160 }
    161 
    162 //有序链表,按值插入
    163 //一二级指针均可
    164 int insertListValue(Node *List, int value){
    165     Node *pCur = List->next;
    166     Node *pPer = NULL;
    167     while (pCur && pCur->data < value){
    168         pPer = pCur;
    169         pCur = pCur->next;
    170     }
    171 
    172     Node *tmpNode = new Node;
    173     if (NULL == tmpNode){
    174         return 0;
    175     }
    176     tmpNode->data = value;
    177     tmpNode->next = pPer->next;
    178     pPer->next = tmpNode;
    179     return 1;
    180 }
    181 
    182 //链表按位置删除
    183 //一二级指针均可
    184 //记得释放结点内存
    185 //如果删除第一个结点,需要操纵头结点
    186 int deleteListPos(Node *List, int pos){
    187     Node *p = List;
    188 
    189     int i = 1;
    190     while (p && i < pos){
    191         p = p->next;
    192         ++i;
    193     }
    194     Node *tmpNode = p->next;
    195     p->next = p->next->next;
    196 
    197     delete tmpNode;
    198     return 1;
    199 }
    200 
    201 //链表按值删除元素
    202 //一二级指针均可
    203 //从第一个结点开始
    204 int deleteListValue(Node *List, int value){
    205     Node *pCur = List->next;
    206     Node *pPer = List;
    207 
    208     while (pCur && pCur->data != value){
    209         pPer = pCur;
    210         pCur = pCur->next;
    211     }
    212     if (pCur == NULL){
    213         return 0;
    214     }
    215     else{
    216         pPer->next = pCur->next;
    217         delete pCur;
    218     }
    219     return 1;
    220 }
    C++完整代码

    结点结构体

      将结点创建为结构体,其中包含数据域和指针域成员,指针域涉及结构体自引用。指针域成员之所以为结点类指针,一是为了编译时能明确结构体大小,二是为了指向下一个结点,因此初始化时不用开辟内存,只需要赋值为NULL即可。当然了,开辟内存也是可以的,这样在删除结点,及清空链表时需要记得将其释放,多此一举,不提倡。

    1 //涉及到结构体自引用
    2 typedef struct Node{
    3     int data;
    4     struct Node *next;
    5 }Node;

    空链表创建(二级指针)

      空链表创建时,建议创建头结点。在插入和删除第一个位置的元素时,需要用结点的二级指针移动头指针,但普通结点的插入和删除并不需要移动头指针。为了便于操作的统一(指插入和删除操作),这里先创建头结点。

      另外,在创建空链表时,需要传入二级指针,主要是为了操作头指针,只要涉及操作头指针的都需要使用二级指针。

     1 //创建空链表
     2 //必须用二级指针,涉及到头指针的创建
     3 int iniList(Node **List){
     4     *List = (Node *)malloc(sizeof(Node));
     5     if (NULL == *List){
     6         return 0;
     7     }
     8 
     9     (*List)->next = NULL; //创建头结点,将其指针域置空
    10     return 1;
    11 }

    链表初始化(二级指针)

      链表初始化,即是创建空链表,并对链表中的n个元素进行赋值。一般来说,有头插法、尾插法两种,头插法是在头结点后插入,尾插法是在链表尾插入。

      头插法

      头插法一般思路:(1)创建带头结点的空链表;(2)创建新结点,对新结点赋值;(3)新结点指向头结点的下一个结点,头结点指向新结点。

     1 //初始化链表(头插法)
     2 //必须二级指针
     3 int iniListHead(Node **List, int n){
     4     *List = (Node *)malloc(sizeof(Node));
     5     if (NULL == *List){
     6         return 0;
     7     }
     8     (*List)->next = NULL;
     9     srand(time(0));
    10 
    11     int i = 0;
    12     while (i < n){
    13         Node *tmpNode = (Node *)malloc(sizeof(Node));
    14         if (NULL == tmpNode){
    15             return 0;
    16         }
    17         tmpNode->data = rand() % 100 + 1;
    18         tmpNode->next = (*List)->next;
    19         (*List)->next = tmpNode;
    20         
    21 
    22         ++i;
    23     }
    24     return 1;
    25 }

      尾插法

      尾插法一般思路:(1)创建带头结点的空链表;(2)创建新结点,对新结点数据域赋值,指针域置空;(3)建立临时变量指向头结点,头结点指向新结点;(4)将临时变量往后移动,指向新结点。

     1 //初始化链表(尾插法)
     2 //必须二级指针
     3 //需要借助辅助变量pCurrent,将每次尾插的新元素当做当前元素
     4 int iniListTail(Node **List, int n){
     5     *List = (Node *)malloc(sizeof(Node));
     6     if (NULL == *List){
     7         return 0;
     8     }
     9     (*List)->next = NULL;
    10     srand(time(0));
    11 
    12     Node *pCurrent = *List;
    13 
    14     int i = 0;
    15     while (i < n){
    16         Node *tmpNode = (Node *)malloc(sizeof(Node));
    17         if (NULL == tmpNode){
    18             return 0;
    19         }
    20         tmpNode->data = rand() % 100 + 1;
    21         tmpNode->next = NULL;
    22         pCurrent->next = tmpNode;
    23         pCurrent = tmpNode;
    24 
    25         ++i;
    26     }
    27     return 1;
    28 }

    链表元素读取(一、二级指针)

      链表元素读取,需要涉及到索引位置。我们知道头结点的数据域没有意义,因此起始位置从第一个结点开始,遍历值从1开始,到pos-1为止,此时p指向pos结点。

     1 //链表获取元素
     2 //一级,二级指针均可
     3 //头结点无意义,从第一个结点开始遍历,i从1开始
     4 //每次都指向下一结点,到pos-1即可
     5 int getList(Node *List, int pos, int *element){
     6     Node *p = List->next;
     7     
     8     int i = 1;
     9     while (p && i < pos){
    10         p = p->next;
    11         ++i;
    12     }
    13     *element = p->data;
    14     return 1;
    15 }

    按位置插入(一、二级指针)

      插入时,需要考虑任意位置,由于头结点的设立,我们不需要单独考虑第一个位置的结点插入。

      一般思路:(1)起始位置从头结点开始,遍历值从1开始,到pos-1为止,此时指向pos-1结点;(2)创建新结点,给新结点数据域赋值;(3)新结点指向pos位置的下一结点,pos位置指向新结点。

     1 //链表按位置插入
     2 //一级,二级指针均可
     3 //从头结点开始,有可能插入在第一个位置,遍历从1开始
     4 int insertListPos(Node *List, int pos, int value){
     5     Node *p = List;
     6 
     7     int i = 1;
     8     while (p && i < pos){
     9         p = p->next;
    10         ++i;
    11     }
    12     Node *tmpNode = (Node *)malloc(sizeof(Node));
    13     tmpNode->data = value;
    14     tmpNode->next = p->next;
    15     p->next = tmpNode;
    16     return 1;
    17 }

    有序链表按值插入(一、二级指针)

      有序链表中涉及到按值插入,按值删除时,需要建立两个临时变量,不同于按位置插入,我们可以在pos前一个停止遍历,按值插入,我们需要遍历找到插入位置,操作插入位置的前一个结点。

      一般思路:(1)从第一个结点开始遍历;(2)创建per变量标记当前结点的前一结点;(3)创建新结点,操作per结点;(4)常规插入操作。

     1 //有序链表,按值插入
     2 //一二级指针均可
     3 int insertListValue(Node *List, int value){
     4     Node *pCur = List->next;
     5     Node *pPer = NULL;
     6     while (pCur && pCur->data < value){
     7         pPer = pCur;
     8         pCur = pCur->next;
     9     }
    10 
    11     Node *tmpNode = (Node *)malloc(sizeof(Node));
    12     if (NULL == tmpNode){
    13         return 0;
    14     }
    15     tmpNode->data = value;
    16     tmpNode->next = pPer->next;
    17     pPer->next = tmpNode;
    18     return 1;
    19 }

    按位置删除(一、二级指针)

      删除时,由于头结点的设立,因此不需要特殊考虑第一个位置的操作和头指针的移动。需要设置临时变量是释放p->next后,后面还会使用p->next的结点,这样会造成访问出错。

      一般思路:(1)起始位置从头结点开始,遍历从1开始,到pos-1为止,此时指向pos-1结点;(2)创建临时变量,指向pos结点;(3)将pos-1结点指向pos的下一结点,释放掉pos结点。

     1 //链表按位置删除
     2 //一二级指针均可
     3 //记得释放结点内存
     4 //如果删除第一个结点,需要操纵头结点
     5 int deleteListPos(Node *List, int pos){
     6     Node *p = List;
     7 
     8     int i = 1;
     9     while (p && i < pos){
    10         p = p->next;
    11         ++i;
    12     }
    13     Node *tmpNode = p->next;
    14     p->next = p->next->next;
    15     
    16     free(tmpNode);
    17     return 1;
    18 }

    按值删除(一、二级指针)

      按值删除与按值插入一样,需要两个临时变量。

      一般思路:(1)起始位置从第一个结点开始,(2)设立per结点指针保存当前结点的上一结点;(3)常规删除操作。

     1 //链表按值删除元素
     2 //一二级指针均可
     3 //从第一个结点开始
     4 int deleteListValue(Node *List, int value){
     5     Node *pCur = List->next;
     6     Node *pPer = List;
     7 
     8     while (pCur && pCur->data != value){
     9         pPer = pCur;
    10         pCur = pCur->next;
    11     }
    12     if (pCur == NULL){ //空链表不删除任何结点
    13         return 0;
    14     }
    15     else{
    16         pPer->next = pCur->next;
    17         free(pCur);
    18     }
    19     return 1;
    20 }

    清空链表(一、二级指针)

      清空链表,只是将链表中的结点删除,并释放掉结点空间,保留头结点,并将头结点的指针域置空。

      一般思路:(1)起始位置从第一个结点开始;(2)设置临时变量q指向当前结点p的下一结点,释放掉当前结点p,将临时变量q赋给p;(3)最后将头结点的指针置空。

     1 //清空链表(不删除头结点)
     2 //一级,二级指针均可
     3 //首先找到链表地址,然后移动至表尾
     4 //判断条件为指针域是否为空,即到达结尾
     5 int deleteList(Node *List){
     6 
     7     //这种方法无法删除尾结点,当p->next是尾结点上一节点时,走一遍程序
     8     //Node *p= List;
     9     //Node *q = NULL;
    10     //
    11     //while (p->next){
    12     //    q = p;
    13     //    free(p);
    14     //    p = q->next;
    15     //}
    16 
    17     Node *p = List->next;
    18     Node *q = NULL;
    19 
    20     while (p){
    21         q = p->next;
    22         free(p);
    23         p = q;
    24     }
    25 
    26     List->next = NULL;
    27     return 1;
    28 }

    销毁链表(二级指针)

      销毁链表,是在清空链表的基础上,删除头结点,将头指针置空,涉及到头指针的操作,需要二级指针。

      思路一:(1)与清空链表操作相同,从第一个结点开始删除;(2)最后释放掉头结点,将头指针置空

      思路二:(1)起始位置从头结点开始删除;(2)将头指针置空

     1 //销毁链表
     2 //必须使用二级指针,销毁头结点和头指针
     3 //最后将链表头指针置空
     4 int desrotyList(Node **List){
     5 
     6     Node *p = *List;
     7     Node *q = NULL;
     8 
     9     //如果为空链表,直接删除头结点
    10     //如果不是空链表,从头结点开始删除
    11     while (p){
    12         q = p->next;
    13         free(p);
    14         p = q;
    15     }
    16     (*List) = NULL;
    17 
    18     //下面是从第一个结点开始删除
    19     //最后释放掉头结点
    20     //Node *p = (*List)->next;
    21     //Node *q = NULL;
    22     //
    23     //while (p){
    24     //    q = p->next;
    25     //    free(p);
    26     //    p = q;
    27     //}
    28     //free(*List);
    29     //(*List) = NULL;
    30 
    31     return 1;
    32 }

     二级指针和一级指针插入解析

    -------------------------------------------------------------------------------------------------------------

    如果上面的资料对你有启发,麻烦点个推荐,让更多人的人看到哦。

    关注公众号【两猿社】,懂点互联网,懂点IC的程序猿,带你丰富项目经验哦。

  • 相关阅读:
    CF1454F Array Partition
    leetcode1883 准时抵达会议现场的最小跳过休息次数
    leetcode1871 跳跃游戏 VII
    leetcode1872 石子游戏VIII
    CF1355C Count Triangles
    CF1245D Shichikuji and Power Grid
    CF1368C Even Picture
    CF1368D AND, OR and square sum
    CF1395C Boboniu and Bit Operations
    SpringBoot和开发热部署
  • 原文地址:https://www.cnblogs.com/qinguoyi/p/10416829.html
Copyright © 2020-2023  润新知