zoukankan      html  css  js  c++  java
  • 【数据结构】单向链表,单向循环链表,双向循环链表

    单向链表

    头文件

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 #ifndef _LINKLIST_H
     7 #define _LINKLIST_H
     8 
     9 #include <stdio.h>
    10 #include <stdlib.h>
    11 #include <stdbool.h>
    12 
    13 typedef int datatype;
    14 
    15 typedef struct node
    16 {
    17     datatype data;
    18     struct node *next;
    19 }linklist,*plinklist;
    20 
    21 extern void linklist_init(plinklist *plist);//初始化链表
    22 extern void linklist_create(plinklist plist, int len);//从头结点创建链表
    23 extern void linklist_create_tail(plinklist plist, int len);//从链表尾创建链表
    24 extern void linklist_sort(plinklist plist);//实现链表的逆转
    25 extern void linklist_show(plinklist plist);//显示链表
    26 
    27 #endif
    View Code

    单向链表

      1 //@ author 成鹏致远
      2 //@ net http://infodown.tap.cn
      3 //@ qq 552158509
      4 //@ blog lcw.cnblogs.com
      5 
      6 #include "linklist.h"
      7 
      8 void linklist_init(plinklist *plist)//初始化链表
      9 {
     10     *plist = (plinklist)malloc(sizeof(linklist));//申请空间
     11     if(*plist == NULL)
     12     {
     13         perror("malloc");
     14         exit(1);
     15     }
     16     (*plist)->next = NULL;//初始化为空
     17 }
     18 
     19 void linklist_create(plinklist plist, int len)//从头结点创建链表
     20 {
     21     plinklist new;
     22 
     23     while(len--)//创建len个结点
     24     {
     25         new = (plinklist)malloc(sizeof(linklist));//申请新空间
     26         if(new == NULL)
     27         {
     28             perror("malloc");
     29             exit(1);
     30         }
     31         new->data = len+1;//完成新结点的赋值
     32         
     33         //现在需要将新申请的结点和已有的结点链接在一起
     34         //注意是在头部插入
     35         new->next = plist->next;//将新申请的new结点插入到链表的最前面
     36         plist->next = new;
     37     }
     38 }
     39 
     40 void linklist_create_tail(plinklist plist, int len)//从链表尾创建链表
     41 {
     42     plinklist new;
     43     plinklist tail = plist;//tail表示链表的最后一个结点,在整个过程中,必须保证头结点(plist)的值不变
     44     int i;
     45 
     46     for(i=0; i<len; i++)
     47     {
     48         new = (plinklist)malloc(sizeof(linklist));//申请新空间
     49         if(new == NULL)
     50         {
     51             perror("malloc");
     52             exit(1);
     53         }
     54         new->data = i+1;
     55         
     56         //现在需要将新申请的结点和已有的结点链接在一起
     57         //注意是在尾部插入
     58         new->next = tail->next;//tail->next为空,new将成为新的尾结点
     59         tail->next = new;//将new结点插入到tail的后面
     60         tail = new;//tail后移,new成为新的尾结点
     61 
     62     }
     63 }
     64 
     65 void linklist_sort(plinklist plist)//实现链表的逆转
     66 {
     67     //思想
     68     //在创建时把最早申请的结点放到了最后面,最后申请的结点放到了最前面
     69     //所以逆转的过程就相当于创建时过程的重复执行,把最前面的又放到最后面
     70     //逆转过程和入栈|出栈是一样的
     71     //出栈|入栈只是为了方便理解
     72 
     73     plinklist p = plist->next;//所有的操作必须保证头结点不变,用p指向链表的第一个元素,负责逆转过程中原链表的的移位
     74     plinklist tem = NULL;//临时变量,负责将原链表元素转移到逆转后的链表(相当于:出栈后入栈)
     75 
     76     plist->next = NULL;//切断头结点与原链表的联系,以便重新建立链表
     77 
     78     while(p != NULL)//p辅助移位,相当于依次出栈
     79     {
     80         tem = p;//标记出栈的元素,即将入栈
     81         p = p->next;//移位,依次出栈
     82 
     83         //将出栈的元素加入到逆转后的链表,相当于再次入栈
     84         //插入过程和从头部创建链表过程一样
     85         tem->next = plist->next;
     86         plist->next = tem;//tem作为链表的第一个元素
     87 
     88     }
     89 }
     90 
     91 void linklist_show(plinklist plist)//显示链表
     92 {
     93     plinklist tem = plist->next;//同样是为了不改变头结点,所以需要临时结点指针
     94 
     95     while(tem != NULL)
     96     {
     97         printf("%d	",tem->data);
     98         tem = tem->next;
     99     }
    100     printf("
    ");
    101 }
    View Code 

    主文件

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 //用单向链表实现数据逆转
     7 //首先建立一个包含若干整数的单向链表,然后实现逆转
     8 
     9 #include "linklist.h"
    10 
    11 int main()
    12 {
    13     plinklist plist;
    14     int length;
    15 
    16     linklist_init(&plist);//完成初始化_
    17 
    18     printf("Pls input the length of linklist:");
    19     scanf("%d",&length);
    20 #if 0
    21     linklist_create(plist,length);//从头结点创建链表
    22     linklist_show(plist);//显示链表
    23     linklist_sort(plist);//逆转链表
    24     linklist_show(plist);
    25 
    26 #else
    27     printf("******************************************
    ");
    28     linklist_create_tail(plist,length);//从尾结点创建链表
    29     linklist_show(plist);//显示链表
    30     linklist_sort(plist);//逆转链表
    31     linklist_show(plist);
    32 
    33 #endif
    34 
    35     return 0;
    36 }
    View Code

    单向循环链表(josephu问题)

    头文件 

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 #ifndef _LINKLIST_H
     7 #define _LINKLIST_H
     8 
     9 #include <stdio.h>
    10 #include <stdlib.h>
    11 #include <stdbool.h>
    12 
    13 typedef int datatype;
    14 
    15 typedef struct node
    16 {
    17     datatype data;
    18     struct node *next;
    19 }linklist,*plinklist;
    20 
    21 
    22 extern void josephu_init(plinklist *plist);//完成初始化
    23 extern void josephu_create(plinklist *plist, int len);//创建链表
    24 extern datatype josephu(plinklist plist);//完成数3出局
    25 extern void josephu_show(plinklist plist);//显示链表
    26 
    27 
    28 #endif
    View Code

    josephu

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 //用单向循环链表现实"数3出局"游戏(Josephu问题)
     7 //首先建立一个包含若干整数的单向循环链表,然后从第一个节点开始数,把数到3的那个节点删除
     8 //接着下一个节点开始数,数到3继续删除,以此类推,打印出最后剩余的那个节点
     9 
    10 #include "linklist.h"
    11 
    12 void josephu_init(plinklist *plist)//完成初始化
    13 {
    14     #if 1//无头结点的初始化
    15          *plist = NULL;
    16     #else//有头结点的初始化
    17          *plist = (plinklist)malloc(sizeof(linklist));
    18          if(*plist == NULL)
    19          {
    20              perror("malloc");
    21              exit(1);
    22          }
    23          (*plist)->next = *plist;
    24     #endif
    25 }
    26 
    27 void josephu_create(plinklist *plist, int len)//创建链表,因为初始化时没有头结点,所以参数需要传*plist
    28 {
    29     plinklist new;
    30     plinklist tail;//尾指针,从链表尾部插入新结点
    31     int i;
    32 
    33     for(i=0; i<len; i++)
    34     {
    35         if(0 == i)//因为无头结点,所以第一次也需要申请空间,并指向自己
    36         {
    37             *plist = (plinklist)malloc(sizeof(linklist));
    38             if(*plist == NULL)
    39             {
    40                 perror("malloc");
    41                 exit(1);
    42             }
    43             (*plist)->data = i+1;
    44             (*plist)->next = *plist;//只有一个结点,指向自己
    45 
    46             tail = *plist;//初始化尾指针
    47         }
    48         else
    49         {
    50             new = (plinklist)malloc(sizeof(linklist));
    51             if(new == NULL)
    52             {
    53                 perror("malloc");
    54                 exit(1);
    55             }
    56             new->data = i+1;
    57             //将新结点new和已有结点连在一起
    58             //注意是在尾部插入
    59             new->next = tail->next;
    60             tail->next = new;//将new结点插入到tail后面
    61             tail = new;//new变成新的尾结点
    62         }
    63     }
    64 }
    65 
    66 datatype josephu(plinklist plist)//完成数3出局
    67 {
    68     plinklist head = plist;//指向每次变化的"头结点",每出局一个人,下一个人将变成头结点
    69     plinklist tem;//临时指针,指向每次出局的人
    70 
    71     while(head != head->next)//只剩下一人时退出循环
    72     {
    73         tem = head->next->next;//tem将出局
    74         head->next->next = tem->next;//tem->next将是下一个"头结点"
    75         head = tem->next;//新"头结点"
    76 
    77         printf("%d	",tem->data);
    78         free(tem);//tem出局
    79     }
    80     return head->data;
    81 }
    82 
    83 void josephu_show(plinklist plist)//显示链表
    84 {
    85     plinklist tem = plist;//保证头结点不变
    86     while(tem != NULL && tem->next != plist)//循环遍历
    87     {
    88         printf("%d	",tem->data);
    89         tem = tem->next;
    90     }
    91     //注意最后一次循环是tem->next = plist,所以最后一个结点并没有输出
    92     printf("%d
    ",tem->data);
    93 
    94 }
    View Code

    主文件

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 //用单向循环链表现实"数3出局"游戏(Josephu问题)
     7 //首先建立一个包含若干整数的单向循环链表,然后从第一个节点开始数,把数到3的那个节点删除
     8 //接着下一个节点开始数,数到3继续删除,以此类推,打印出最后剩余的那个节点
     9 
    10 #include "linklist.h"
    11 
    12 int main()
    13 {
    14     plinklist plist;
    15     datatype result;
    16     int len;
    17 
    18     josephu_init(&plist);//完成初始化
    19 
    20     printf("Pls input the length of josephu:");
    21     scanf("%d",&len);
    22 
    23     josephu_create(&plist,len);//创建josephu链表
    24     josephu_show(plist);//显示josephu链表
    25     
    26     result = josephu(plist);//解决方案
    27     printf("
    The last is %d
    ",result);
    28 
    29     return 0;
    30 }
    View Code

     


     双向循环链表

    头文件

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 #ifndef _DOUBLELIST_H
     7 #define _DOUBLELIST_H
     8 
     9 #include <stdio.h>
    10 #include <stdlib.h>
    11 #include <stdbool.h>
    12 
    13 typedef int datatype;
    14 
    15 typedef struct node
    16 {
    17     datatype data;
    18     struct node *next,*prior;
    19 }double_list,*double_plist;
    20 
    21 extern void double_init(double_plist *plist);//双向链表的初始化
    22 extern void double_sort(double_plist plist);//完成双向链表的奇数升序偶数降序排列
    23 extern void double_create(double_plist plist, int len);//头插法创建双向链表
    24 extern void double_show(double_plist plist);//显示双向链表
    25 
    26 #endif
    View Code

     双向循环链表

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 //用双向循环链表实现顺序递增存储若干个自然数
     7 //比如输入一个整数10,则建立一个双向循环链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10
     8 //然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来
     9 
    10 #include "double_list.h"
    11 
    12 void double_init(double_plist *plist)//双向链表的初始化
    13 {
    14     *plist = (double_plist)malloc(sizeof(double_list));
    15     if(*plist == NULL)
    16     {
    17         perror("malloc");
    18         exit(1);
    19     }
    20 
    21     (*plist)->next = (*plist)->prior = *plist;//双向链表的前后指针都指向自己
    22 
    23 }
    24 
    25 void double_sort(double_plist plist)//完成双向链表的奇数升序偶数降序排列
    26 {
    27     double_plist pnext = plist->next;//指向链表的第一个节点
    28     double_plist prior = plist->prior;//指向链表的最后一个节点
    29     double_plist tem = NULL;//临时指针,用于辅助定位将被移动的节点
    30 
    31     while(pnext != prior)//没有到达链表尾
    32     {
    33         if(pnext->data%2 !=0)//为奇数,直接跳过
    34             pnext = pnext->next;
    35         else//为偶数,将pnext移动到偶数后面一位奇数位置,用tem指向回去辅助移动偶数链表节点
    36         {
    37             pnext = pnext->next;
    38 
    39             //将pnext前面的节点剪切出来
    40             tem = pnext->prior;//tem指向要被移动的节点
    41             pnext->prior = tem->prior;//将奇数节点前向指针连接起来
    42             tem->prior->next = pnext;//将奇数节点后向指针连接起来
    43 
    44             //将偶数节点(tem)插入到链表尾(prior)
    45             tem->next = prior->next;//tem将成为新的尾结点
    46             prior->next->prior = tem;//链表首尾相连
    47             //prior和新的尾结点tem相连
    48             tem->prior = prior;
    49             prior->next = tem;
    50         }
    51     }
    52 }
    53 
    54 void double_create(double_plist plist, int len)//头插法创建双向链表
    55 {
    56     double_plist new;
    57     while(len--)//创建len个节点
    58     {
    59         new = (double_plist)malloc(sizeof(double_list));
    60         if(new == NULL)
    61         {
    62             perror("malloc");
    63             exit(1);
    64         }
    65         new->data = len+1;
    66 
    67         //向plist后面插入一个新的节点
    68         //双向链表的头插法
    69         new->next = plist->next;
    70         plist->next->prior = new;
    71         new->prior = plist;
    72         plist->next = new;
    73     }
    74 }
    75 
    76 void double_show(double_plist plist)//显示双向链表
    77 {
    78     double_plist tem = plist->next;//保证头结点不变
    79 
    80     while(tem != plist)//遍历一个循环
    81     {
    82         printf("%d	",tem->data);
    83         tem = tem->next;
    84     }
    85     printf("
    ");
    86 }
    View Code

    主文件 

     1 //@ author 成鹏致远
     2 //@ net http://infodown.tap.cn
     3 //@ qq 552158509
     4 //@ blog lcw.cnblogs.com
     5 
     6 //用双向循环链表实现顺序递增存储若干个自然数
     7 //比如输入一个整数10,则建立一个双向循环链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10
     8 //然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来
     9 
    10 #include "double_list.h"
    11 
    12 int main()
    13 {
    14     double_plist plist;
    15     int len;
    16 
    17     double_init(&plist);//双向链表初始化
    18 
    19     printf("Pls input the length of double list:");
    20     scanf("%d",&len);
    21 
    22     double_create(plist,len);//创建双向链表
    23     double_show(plist);//显示双向链表
    24 
    25     double_sort(plist);//完成奇数升序偶数降序排序
    26     double_show(plist);
    27 
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    Linux安装git报错 expected specifier-qualifier-list before ‘z_stream’
    Error: Cannot retrieve repository metadata (repomd.xml) for repository: FedoraPeople-sea. Please verify its path and try again
    Linux文件夹文件创建、删除
    confluence 常见问题处理
    git 删除本地和远程服务器分支
    yii DbCriteria相关属性常用方法
    git pull 撤销误操作
    如何在linux上按照行拆分大文件
    linux中rz的用法
    mac版本自带2.7.10版本的python情况下如何安装和使用python3.x
  • 原文地址:https://www.cnblogs.com/lcw/p/3235005.html
Copyright © 2011-2022 走看看