zoukankan      html  css  js  c++  java
  • C语言实现单链表,并完成链表常用API函数

    C语言实现单链表,并完成链表常用API函数:

      1.链表增、删、改、查。

      2.打印链表、反转打印、打印环形链表。

      3.链表排序、链表冒泡排序、链表快速排序。

      4.求链表节点个数(普通方法、递归方法)。

      5.链表反转(普通方法、递归方法)。

      6.链表合并。

      7.获取链表中间节点。

      8.判断链表是否有环。

    LinkList.h :

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 struct LinkNode
     5 {
     6     int data;
     7     struct LinkNode *pNext;
     8 };
     9 
    10 typedef struct LinkNode Node;    //简化类型
    11 
    12 void init(Node *phead);                            //初始化
    13 Node *addBack(Node *phead, int data);            //尾插法:尾部添加节点
    14 void addHead(Node *phead, int data);            //头插法:头部添加节点
    15 
    16 void ShowAll(Node *phead);                        //显示链表
    17 void revShowAll(Node *phead);                    //反转显示链表                                
    18 void ShowCircleLink(Node *phead);                //显示环形链表
    19 
    20 Node *searchFirst(Node *phead, int findData);    //查找
    21 
    22 Node *changeFirst(Node *phead, int findData, int newData);    //修改
    23 
    24 Node *delFirst(Node *phead, int delData);        //删除
    25 
    26 Node *insertFirst(Node *phead, int insertData,int newData);        //插入
    27 
    28 void bubbleSort(Node *phead);                    //冒泡排序
    29 
    30 void quickSort(Node *pbegin, Node *pback);        //快速排序法:(双冒泡)
    31 Node *fen(Node *pbegin, Node *pback);            //分段
    32 
    33 int getNum1(Node *phead);                        //求链表节点个数
    34 int getNum2(Node *phead);                        //求链表节点个数(递归)
    35 
    36 Node *revList1(Node *phead);                    //链表反转(普通方法)
    37 Node *revList2(Node *phead);                    //链表反转(递归方法)
    38 
    39 //将链表phead1和phead2合并到phead3,并返回链表phead3
    40 Node *mergeList(Node *phead3, Node *phead1, Node *phead2);        //链表合并
    41 
    42 Node *getMid(Node *phead);                        //获取链表的中间节点
    43 
    44 int judgeCircle(Node *phead);                    //判断链表是否有环

    LinkList.c :

      1 #include "LinkList.h"
      2 
      3 //初始化
      4 void init(Node *phead)
      5 {
      6     phead->pNext = NULL;
      7     phead->data = 0;
      8 }
      9 
     10 //显示链表
     11 void ShowAll(Node *phead)
     12 {
     13     if (phead == NULL)
     14         return;
     15     else
     16     {
     17         printf("%4d", phead->data);
     18         //printf("%d,%p,%p
    ", phead->data, phead, phead->pNext);
     19         ShowAll(phead->pNext);                                    //跳到下一个节点
     20 
     21     }
     22 }
     23 
     24 //反转显示链表
     25 void revShowAll(Node *phead)
     26 {
     27     if (phead == NULL)
     28         return;
     29     else
     30     {
     31         printf("%d,%p,%p
    ", phead->data, phead, phead->pNext);
     32         ShowAll(phead->pNext);                                    //跳到下一个节点
     33 
     34     }
     35 }
     36 
     37 //显示环形链表
     38 void ShowCircleLink(Node *phead)
     39 {
     40     if (phead == NULL)
     41         return;
     42     else
     43     {
     44         Node *p = phead;
     45         for (; p->pNext != phead; p = p->pNext)
     46             printf("%4d", p->data);
     47 
     48         printf("%4d", p->data);    //还需要再打印最后一个元素
     49 
     50     }
     51 }
     52 
     53 //尾插法:尾部添加节点  (改变了头指针,改变一个指针,要么二级指针,要么用返回值给指针赋值,这里采用返回值)
     54 Node *addBack(Node *phead, int data)
     55 {
     56     Node *pnew = malloc(sizeof(Node));    //构建新的节点
     57     pnew->data = data;                    //新节点赋值
     58     pnew->pNext = NULL;
     59 
     60     if (phead == NULL)                    //phead为空,直接连接
     61         phead = pnew;
     62     else
     63     {
     64         Node *ptemp = phead;            //备份一下头指针
     65         while (ptemp->pNext != NULL)
     66         {
     67             ptemp = ptemp -> pNext;        //循环前进
     68         }
     69         ptemp->pNext = pnew;            //链接
     70     }
     71 
     72     return phead;
     73 }
     74 
     75 //头插法:头部添加节点 (采用二级指针的方法)
     76 void addHead(Node **pphead, int data)
     77 {
     78     Node *pnew = malloc(sizeof(Node));    //构建新的节点
     79     pnew->data = data;                    //新节点赋值
     80     pnew->pNext = NULL;
     81 
     82     if(*pphead==NULL)
     83         pphead = pnew;
     84     else
     85     {
     86         pnew->pNext = *pphead;
     87         *pphead = pnew;
     88     }
     89 }
     90 
     91 //查找
     92 Node *searchFirst(Node *phead, int findData)
     93 {
     94     for (Node *p = phead; p != NULL; p = p->pNext)
     95     {
     96         if (p->data == findData)
     97         {
     98             return p;        //返回找到的指针位置
     99         }
    100     }
    101 
    102     return NULL;
    103 }
    104 
    105 //修改
    106 Node *changeFirst(Node *phead, int findData, int newData)
    107 {
    108     for (Node *p = phead; p != NULL; p = p->pNext)
    109     {
    110         if (p->data == findData)
    111         {
    112             p->data = newData;
    113             return p;        //返回找到的指针位置
    114         }
    115     }
    116 
    117     return NULL;
    118 }
    119 
    120 //删除
    121 Node *delFirst(Node *phead, int delData)
    122 {
    123     Node *p1=NULL, *p2=NULL;        //此时需要双指针
    124     p1 = phead;            //保存头结点
    125 
    126     while (p1 != NULL)
    127     {
    128         if (p1->data != delData)
    129         {
    130             p2 = p1;        //p2保存的是p1的上一个位置
    131             p1 = p1->pNext;
    132         }
    133         else
    134             break;
    135     }
    136 
    137     if (p1 != phead)
    138     {
    139         p2->pNext = p1->pNext;    //跳过p1
    140         free(p1);                //删除p1
    141     }
    142     else
    143     {
    144         phead = phead->pNext;
    145         free(p1);                //头部删除
    146     }
    147 
    148     return phead;
    149 }
    150 
    151 //插入
    152 Node *insertFirst(Node *phead, int insertData, int newData)
    153 {
    154     Node *p1 = NULL, *p2 = NULL;        //此时需要双指针
    155     p1 = phead;            //保存头结点
    156 
    157     while (p1 != NULL)
    158     {
    159         if (p1->data != insertData)
    160         {
    161             p2 = p1;        //p2保存的是p1的上一个位置
    162             p1 = p1->pNext;    //向前移动
    163         }
    164         else
    165             break;
    166     }
    167 
    168     Node *pnew = malloc(sizeof(Node));    //构建新的节点
    169     pnew->data = newData;                //新节点赋值
    170     pnew->pNext = NULL;
    171 
    172     if (phead == p1)
    173     {
    174         pnew->pNext = phead;    //保存头结点
    175         phead = pnew;            //头部插入
    176     }
    177     else
    178     {
    179         pnew->pNext = p1;
    180         p2->pNext = pnew;        //插入
    181     }
    182 
    183     return phead;
    184 }
    185 
    186 //冒泡排序
    187 void bubbleSort(Node *phead)
    188 {
    189     //数组可以随机访问任何一个元素,可以规避一些比较
    190     //链表找到N个元素,必须先遍历N-1个元素
    191     for (Node *p1 = phead; p1 != NULL; p1 = p1->pNext)
    192     {
    193         for (Node *p2 = phead; p2 != NULL; p2 = p2->pNext)
    194         {
    195             if (p1->data < p2->data)
    196             {
    197                 int temp;
    198                 temp = p1->data;
    199                 p1->data = p2->data;
    200                 p2->data = temp;
    201             }
    202         }
    203     }
    204 }
    205 
    206 Node *fen(Node *pbegin, Node *pback)
    207 {
    208     int key = pbegin->data;        //以第一个数据为分段
    209 
    210     Node *p = pbegin;            //第一个节点
    211     Node *q = pbegin->pNext;    //第二个节点
    212 
    213     while (q != pback)
    214     {
    215         if (q->data < key)
    216         {
    217             p = p->pNext;        //循环下一个节点
    218 
    219             int temp = p->data;    //交换
    220             p->data = q->data;
    221             q->data = temp;
    222         }
    223         q = q->pNext;            //循环第二个指针
    224 
    225         printf("
    枢轴为:(%d)", key);
    226         printf("
    此时数:");
    227         ShowAll(pbegin);
    228 
    229     }
    230 
    231     int temp = p->data;    //交换
    232     p->data = pbegin->data;
    233     pbegin->data = temp;
    234 
    235     printf("
    
    交换值:");
    236     ShowAll(pbegin);
    237     printf("
    -----------------------------------------------");
    238 
    239     return p;
    240 }
    241 
    242 //快速排序法:(双冒泡)
    243 void quickSort(Node *pbegin,Node *pback)
    244 {
    245     if (pbegin != pback)
    246     {
    247         Node *pfen = fen(pbegin, pback);    //取中间点,分成两段分别再进行快排
    248 
    249         quickSort(pbegin, pfen);            //前半段快排
    250         quickSort(pfen->pNext, pback);        //后半段快排
    251     }
    252 }
    253 
    254 //求链表节点个数(普通方法)
    255 int getNum1(Node *phead)
    256 {
    257     int i = 0;
    258     for (; phead != NULL; phead = phead->pNext)
    259     {
    260         i++;
    261     }
    262     return i;
    263 }
    264 
    265 //求链表节点个数(递归)
    266 int getNum2(Node *phead)
    267 {
    268     if (phead == NULL)
    269         return 0;
    270     else
    271         return 1 + getNum2(phead->pNext);
    272 }
    273 
    274 //链表反转(普通方法)
    275 Node *revList1(Node *phead)
    276 {
    277     if (phead == NULL || phead->pNext == NULL)
    278         return phead;
    279     else
    280     {
    281         Node *pre = NULL;
    282         Node *pcur = NULL;
    283         Node *pnext = NULL;
    284 
    285         pre = phead;
    286         pcur = phead->pNext;
    287         while (pcur != NULL)
    288         {
    289             pnext = pcur->pNext;    //备份下一个节点
    290             pcur->pNext = pre;        //第一个节点指向NULL,此时pre指向NULL(指针反转)
    291             
    292             pre = pcur;                //前进
    293             pcur = pnext;            //轮替前进
    294         }
    295 
    296         phead->pNext = NULL;        //注意尾节点置空
    297         phead = pre;
    298     }
    299 
    300     return phead;
    301 }
    302 
    303 //链表反转(递归方法)
    304 Node *revList2(Node *phead)
    305 {
    306     if (phead == NULL || phead->pNext == NULL)
    307         return phead;
    308     else
    309     {
    310         Node *pnext = phead->pNext;        //顺序
    311 
    312         Node *Head = revList2(pnext);    //轮询所有的节点,递归调用
    313 
    314         pnext->pNext = phead;
    315 
    316         phead->pNext = NULL;            //逆序
    317 
    318         return Head; 
    319     }
    320 }
    321 
    322 //链表合并
    323 Node *mergeList(Node *phead3, Node *phead1, Node *phead2)
    324 {
    325     Node *pcur1 = phead1;
    326     Node *pcur2 = phead2;
    327 
    328     while (pcur1 != NULL || pcur2 != NULL)
    329     {
    330         if (pcur1 != NULL && pcur2 != NULL)
    331         {
    332             if (pcur1->data < pcur2->data)
    333             {
    334                 phead3 = addBack(phead3, pcur1->data);
    335                 pcur1 = pcur1->pNext;
    336             }
    337             else
    338             {
    339                 phead3 = addBack(phead3, pcur2->data);
    340                 pcur2 = pcur2->pNext;
    341             }
    342         }
    343         else
    344         {
    345             while (pcur1 != NULL)
    346             {
    347                 phead3 = addBack(phead3, pcur1->data);
    348                 pcur1 = pcur1->pNext;
    349             }
    350             while (pcur2 != NULL)
    351             {
    352                 phead3 = addBack(phead3, pcur2->data);
    353                 pcur2 = pcur2->pNext;
    354             }
    355 
    356             break;
    357         }
    358     }
    359 
    360     return phead3;
    361 }
    362 
    363 //获取链表的中间节点
    364 Node *getMid(Node *phead)
    365 {
    366     if (phead == NULL || phead->pNext == NULL)
    367         return phead;
    368     else
    369     {
    370         Node *p1 = phead;            //一次前进一步
    371         Node *p2 = phead;            //一次前进两步
    372 
    373         while (p2->pNext != NULL)    //注意循环条件,而不是p2 != NULL
    374         {
    375             p1 = p1->pNext;
    376             p2 = p2->pNext;
    377             if (p2->pNext != NULL)
    378                 p2 = p2->pNext;
    379         }
    380 
    381         return p1;
    382     }
    383 }
    384 
    385 //判断链表是否有环
    386 int judgeCircle(Node *phead)
    387 {
    388     int flag = 0;
    389     for (Node *p1 = phead, *p2 = phead; p1 != NULL && p2 != NULL; p1 = p1->pNext, p2 = p2->pNext)    //死循环
    390     {    
    391         if(p2->pNext!=NULL)    //p2一次前进两步,而p1一次前进一步
    392             p2 = p2->pNext;
    393 
    394         if (p1 == p2)
    395         {
    396             flag == 1;        //p1追上了p2,有环
    397             break;
    398         }
    399             
    400         
    401     }
    402 
    403     return flag;
    404 }

    main.c :

      1 #include "LinkList.h"
      2 
      3 void main()
      4 {
      5     Node *phead = NULL;
      6     //init(phead);    //初始化,头结点不分配内存,这里不能初始化头结点
      7 
      8     phead = addBack(phead, 14);        //尾插
      9     phead = addBack(phead, 15);
     10     phead = addBack(phead, 16);
     11     phead = addBack(phead, 8);
     12     phead = addBack(phead, 12);
     13     phead = addBack(phead, 13);
     14 
     15     //addHead(&phead, 9);            //头插
     16     //addHead(&phead, 22);
     17     //addHead(&phead, 41);
     18     //addHead(&phead, 18);
     19     //ShowAll(phead);
     20 
     21     //Node *pfind = searchFirst(phead, 13);
     22     //pfind->data = 33;
     23     //ShowAll(phead);
     24 
     25     //Node *pchange = changeFirst(phead, 14,93);
     26     //ShowAll(phead);
     27 
     28     //ShowAll(phead);
     29     //printf("
    
    ");
     30     //phead = delFirst(phead, 24);
     31     //ShowAll(phead);
     32 
     33     //printf("
    
    ");
     34     //insertFirst(phead, 11, 100);
     35     //ShowAll(phead);
     36 
     37     printf("排序前:");
     38     ShowAll(phead);
     39     printf("
    
    ");
     40 
     41     //bubbleSort(phead);
     42     quickSort(phead, NULL);
     43     
     44     printf("
    
    ");
     45     printf("排序后:");
     46     ShowAll(phead);
     47     printf("
    ");
     48 
     49     printf("%d
    ", getNum2(phead));
     50 
     51     phead = revList1(phead);
     52     ShowAll(phead);
     53     printf("
    ");
     54     phead = revList2(phead);
     55     ShowAll(phead);
     56     printf("
    ");
     57 
     58     Node *phead1 = NULL;
     59     phead1 = addBack(phead1, 1);
     60     phead1 = addBack(phead1, 3);
     61     phead1 = addBack(phead1, 5);
     62     phead1 = addBack(phead1, 7);
     63     phead1 = addBack(phead1, 9);
     64 
     65     Node *phead2 = NULL;
     66     phead2 = addBack(phead2, 2);
     67     phead2 = addBack(phead2, 4);
     68     phead2 = addBack(phead2, 6);
     69     phead2 = addBack(phead2, 8);
     70 
     71     printf("
    
    
    ");
     72     ShowAll(phead1);
     73     printf("
    ");
     74     ShowAll(phead2);
     75     printf("
    ");
     76 
     77     Node *phead3 = NULL;
     78     phead3 = mergeList(phead3, phead1, phead2);
     79     ShowAll(phead3);
     80     printf("
    ");
     81 
     82     Node *pmid = getMid(phead3);
     83     printf("%d
    ", pmid->data);
     84 
     85     Node *phead4 = NULL;
     86     phead4 = addBack(phead4, 1);
     87     phead4 = addBack(phead4, 2);
     88     phead4 = addBack(phead4, 3);
     89     phead4 = addBack(phead4, 4);
     90     phead4 = addBack(phead4, 5);
     91     phead4 = addBack(phead4, 6);
     92     phead4 = addBack(phead4, 7);
     93 
     94     Node *p = phead4;
     95     for (; p->pNext != NULL; p = p->pNext)
     96     {
     97     }
     98     p->pNext = phead4;
     99 
    100     ShowCircleLink(phead4);    //打印环形链表
    101     printf("
    ");
    102     printf("%d
    ", judgeCircle(phead4));
    103 
    104     system("pause");
    105 }
  • 相关阅读:
    用Navicat运行一个比较大的.sql文件时报错:[Err] 2006
    访问laravel的api接口返回200和html代码,没有返回打印的一些数据
    英文字母和中文汉字在不同字符集编码下的字节数
    PHP curl详解
    php判断图片是否损坏
    png转为jpg
    win10快速解决警告:libpng warning: iCCP: known incorrect sRGB profile
    PHP:cURL error 60: SSL certificate unable to get local issuer certificate
    windows mysql服务出错
    go 切片对数组的修改,切片的扩容
  • 原文地址:https://www.cnblogs.com/si-lei/p/9493002.html
Copyright © 2011-2022 走看看