单链表反序,逆序的两种方法

我先画一个单链表,这个单链表有4个元素。我的思路就是,每次把第二个元素提到最前面来。比如下面是第一次交换,我们先让头结点的next域指向结点a2,再让结点a1的next域指向结点a3,最后将结点a2的next域指向结点a1,就完成了第一次交换。

http://www.nowamagic.net/librarys/images/201209/2012_09_13_01.jpg

第一次交换

然后进行相同的交换将结点a3移动到结点a2的前面,然后再将结点a4移动到结点a3的前面就完成了反转。


http://www.nowamagic.net/librarys/images/201209/2012_09_13_02.jpg

第二次交换

http://www.nowamagic.net/librarys/images/201209/2012_09_13_03.jpg

第三次交换


步骤:

  1. 定义当前结点 current,初始值为首元结点,current = L->next;
  2. 定义当前结点的后继结点 pnext, pnext = current->next; 
  3. 只要 pnext 存在,就执行以下循环:
    • 定义新节点 prev,它是 pnext的后继结点,prev = pnext->next;
    • 把pnext的后继指向current, pnext->next = current;
    • 此时,pnext 实际上已经到了 current 前一位成为新的current,所以这个时候 current 结点实际上成为新的 pnext,current = pnext;
    • 此时,新的 current 就是 pnext,current = pnext;
    • 而新的 pnext 就是 prev,pnext = prev;
  4. 最后将头结点与 current 重新连上即可,L->next = current;

函数设计如下:

  1. /* 单链表反转/逆序 */  
  2. Status ListReverse(LinkList L)  
  3. {  
  4.     LinkList current,pnext,prev;  
  5.     if(L == NULL || L->next == NULL)  
  6.         return L;  
  7.     current = L->next;  /* p1指向链表头节点的下一个节点 */  
  8.     pnext = current->next;  
  9.     current->next = NULL;  
  10.     while(pnext)  
  11.     {  
  12.         prev = pnext->next;  
  13.         pnext->next = current;  
  14.         current = pnext;  
  15.         pnext = prev;  
  16.         printf("交换后:current = %d,next = %d \n",current->data,current->next->data);  
  17.     }  
  18.     //printf("current = %d,next = %d \n",current->data,current->next->data);  
  19.     L->next = current;  /* 将链表头节点指向p1 */  
  20.     return L;  
  21. }  
/* 单链表反转/逆序 */
Status ListReverse(LinkList L)
{
    LinkList current,pnext,prev;
    if(L == NULL || L->next == NULL)
        return L;
    current = L->next;  /* p1指向链表头节点的下一个节点 */
    pnext = current->next;
    current->next = NULL;
    while(pnext)
    {
        prev = pnext->next;
        pnext->next = current;
        current = pnext;
        pnext = prev;
        printf("交换后:current = %d,next = %d \n",current->data,current->next->data);
    }
    //printf("current = %d,next = %d \n",current->data,current->next->data);
    L->next = current;  /* 将链表头节点指向p1 */
    return L;
}

其实在你写函数的时候,我也写了个函数,也能运行。思路也差不多,不过你的current一直是表的第一个结点,我这里的current始终是首元结点的值,我的函数需要每次对pnext重新赋值。一会解释下。


  1. Status ListReverse2(LinkList L)  
  2. {  
  3.     LinkList current, p;  
  4.   
  5.     if (L == NULL)  
  6.     {  
  7.         return NULL;  
  8.     }  
  9.     current = L->next;  
  10.     while (current->next != NULL)  
  11.     {  
  12.         p = current->next;  
  13.         current->next = p->next;  
  14.         p->next = L->next;  
  15.         L->next = p;  
  16.     }  
  17.     return L;  
  18. }  
Status ListReverse2(LinkList L)
{
    LinkList current, p;

    if (L == NULL)
    {
        return NULL;
    }
    current = L->next;
    while (current->next != NULL)
    {
        p = current->next;
        current->next = p->next;
        p->next = L->next;
        L->next = p;
    }
    return L;
}

  1. p = current->next; p 就相当于前面的 pnext。(图1中a2即为p)
  2. current->next = p->next; p->next 就相当于 prev的角色,这句代码意思是 current 的后继指向 prev.(相当于图1中a1->next = a3(a2->next))
  3. p->next = L->next; 这句就是 p 的后继直接指向首元节点。(相当于图1中a2->next = a1)
  4. L->next = p; 然后再将头结点指向 p。(相当于图1中L->next = a2)
参照图就很容易理解上面的步骤了。我觉得我这么写比你的清晰一些。我先将current指向prev,再将pnext指向current,最后将头结点指向pnext。

运行结果

  1. 整体创建L的元素(头插法):  
  2. // 原链表,current = 68, pnext = 55,68指向18,55指向18,头结点指向55  
  3. -> 68 -> 55 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67  
  4.   
  5. // 第一次交换后,原链表变成这样  
  6. -> 55 -> 68 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67  
  7. // 进行第二次交换,pnext = 18,68指向45,18变成头结点  
  8. -> 18 -> 55 -> 68 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67  
  9. // 进行第三次交换,pnext = current->next = 45,68指向41,45变成头结点  
  10. -> 45 -> 18 -> 55 -> 68 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67  
  11. // ……  
  12. -> 41 -> 45 -> 18 -> 55 -> 68 -> 43 -> 5 -> 28 -> 80 -> 67  
  13.   
  14. -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 5 -> 28 -> 80 -> 67  
  15.   
  16. -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 28 -> 80 -> 67  
  17.   
  18. -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 80 -> 67  
  19.   
  20. -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 67  
  21. // current 68 没有后继,反转结束  
  22. -> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68  
  23.   
  24.   
  25. 反转L后  
  26. -> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68  
整体创建L的元素(头插法):
// 原链表,current = 68, pnext = 55,68指向18,55指向18,头结点指向55
-> 68 -> 55 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67

// 第一次交换后,原链表变成这样
-> 55 -> 68 -> 18 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67
// 进行第二次交换,pnext = 18,68指向45,18变成头结点
-> 18 -> 55 -> 68 -> 45 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67
// 进行第三次交换,pnext = current->next = 45,68指向41,45变成头结点
-> 45 -> 18 -> 55 -> 68 -> 41 -> 43 -> 5 -> 28 -> 80 -> 67
// ……
-> 41 -> 45 -> 18 -> 55 -> 68 -> 43 -> 5 -> 28 -> 80 -> 67

-> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 5 -> 28 -> 80 -> 67

-> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 28 -> 80 -> 67

-> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 80 -> 67

-> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68 -> 67
// current 68 没有后继,反转结束
-> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68


反转L后
-> 67 -> 80 -> 28 -> 5 -> 43 -> 41 -> 45 -> 18 -> 55 -> 68

最后附上完整代码,反转有两个函数。

  • 方法1,current始终保持在第一位,pnext与prev遍历并完成交换。
  • 方法2,current始终是原链表的第一个数,然后把pnext不断移动到首位。
  1. #include "stdio.h"  
  2.   
  3. #define OK 1  
  4. #define ERROR 0  
  5. #define TRUE 1  
  6. #define FALSE 0  
  7.   
  8. #define MAXSIZE 20 /* 存储空间初始分配量 */  
  9.   
  10. typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */  
  11. typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */  
  12.   
  13. typedef struct Node  
  14. {  
  15.     ElemType data;  
  16.     struct Node *next;  
  17. }Node;  
  18. /* 定义LinkList */  
  19. typedef struct Node *LinkList;  
  20.   
  21. /* 初始化顺序线性表 */  
  22. Status InitList(LinkList *L)  
  23. {  
  24.     *L=(LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */  
  25.     if(!(*L)) /* 存储分配失败 */  
  26.     {  
  27.         return ERROR;  
  28.     }  
  29.     (*L)->next=NULL/* 指针域为空 */  
  30.   
  31.     return OK;  
  32. }  
  33.   
  34. /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */  
  35. int ListLength(LinkList L)  
  36. {  
  37.     int i=0;  
  38.     LinkList p=L->next; /* p指向第一个结点 */  
  39.     while(p)  
  40.     {  
  41.         i++;  
  42.         p=p->next;  
  43.     }  
  44.     return i;  
  45. }  
  46.   
  47. /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */  
  48. Status ClearList(LinkList *L)  
  49. {  
  50.     LinkList p,q;  
  51.     p=(*L)->next;           /*  p指向第一个结点 */  
  52.     while(p)                /*  没到表尾 */  
  53.     {  
  54.         q=p->next;  
  55.         free(p);  
  56.         p=q;  
  57.     }  
  58.     (*L)->next=NULL;        /* 头结点指针域为空 */  
  59.     return OK;  
  60. }  
  61.   
  62. /* 初始条件:顺序线性表L已存在 */  
  63. /* 操作结果:依次对L的每个数据元素输出 */  
  64. Status ListTraverse(LinkList L)  
  65. {  
  66.     LinkList p=L->next;  
  67.     while(p)  
  68.     {  
  69.         visit(p->data);  
  70.         p=p->next;  
  71.     }  
  72.     printf("\n");  
  73.     return OK;  
  74. }  
  75.   
  76. Status visit(ElemType c)  
  77. {  
  78.     printf("-> %d ",c);  
  79.     return OK;  
  80. }  
  81.   
  82. /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */  
  83. /* 操作结果:用e返回L中第i个数据元素的值 */  
  84. Status GetElem(LinkList L,int i,ElemType *e)  
  85. {  
  86.     int j;  
  87.     LinkList p;     /* 声明一结点p */  
  88.     p = L->next;     /* 让p指向链表L的第一个结点 */  
  89.     j = 1;      /*  j为计数器 */  
  90.     while (p && j < i)  /* p不为空或者计数器j还没有等于i时,循环继续 */  
  91.     {  
  92.         p = p->next;  /* 让p指向下一个结点 */  
  93.         ++j;  
  94.     }  
  95.     if ( !p || j>i )  
  96.         return ERROR;  /*  第i个元素不存在 */  
  97.     *e = p->data;   /*  取第i个元素的数据 */  
  98.     return OK;  
  99. }  
  100.   
  101. /* 初始条件:顺序线性表L已存在 */  
  102. /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */  
  103. /* 若这样的数据元素不存在,则返回值为0 */  
  104. int LocateElem(LinkList L,ElemType e)  
  105. {  
  106.     int i=0;  
  107.     LinkList p=L->next;  
  108.     while(p)  
  109.     {  
  110.         i++;  
  111.         if(p->data==e) /* 找到这样的数据元素 */  
  112.                 return i;  
  113.         p=p->next;  
  114.     }  
  115.   
  116.     return 0;  
  117. }  
  118.   
  119. /*  随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */  
  120. void CreateListHead(LinkList *L, int n)  
  121. {  
  122.     LinkList p;  
  123.     int i;  
  124.     srand(time(0));                         /* 初始化随机数种子 */  
  125.     *L = (LinkList)malloc(sizeof(Node));  
  126.     (*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */  
  127.     for (i=0; i < n; i++)  
  128.     {  
  129.         p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */  
  130.         p->data = rand()%100+1;             /*  随机生成100以内的数字 */  
  131.         p->next = (*L)->next;  
  132.         (*L)->next = p;                      /*  插入到表头 */  
  133.     }  
  134. }  
  135.   
  136. /*  随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */  
  137. void CreateListTail(LinkList *L, int n)  
  138. {  
  139.     LinkList p,r;  
  140.     int i;  
  141.     srand(time(0));                      /* 初始化随机数种子 */  
  142.     *L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */  
  143.     r=*L;                                /* r为指向尾部的结点 */  
  144.     for (i=0; i < n; i++)  
  145.     {  
  146.         p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */  
  147.         p->data = rand()%100+1;           /*  随机生成100以内的数字 */  
  148.         r->next=p;                        /* 将表尾终端结点的指针指向新结点 */  
  149.         r = p;                            /* 将当前的新结点定义为表尾终端结点 */  
  150.     }  
  151.     r->next = NULL;                       /* 表示当前链表结束 */  
  152. }  
  153.   
  154. /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */  
  155. /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */  
  156. Status ListInsert(LinkList *L,int i,ElemType e)  
  157. {  
  158.     int j;  
  159.     LinkList p,s;  
  160.     p = *L;     /* 声明一个结点 p,指向头结点 */  
  161.     j = 1;  
  162.     while (p && j < i)     /* 寻找第i个结点 */  
  163.     {  
  164.         p = p->next;  
  165.         ++j;  
  166.     }  
  167.     if (!p || j > i)  
  168.         return ERROR;   /* 第i个元素不存在 */  
  169.     s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */  
  170.     s->data = e;  
  171.     s->next = p->next;      /* 将p的后继结点赋值给s的后继  */  
  172.     p->next = s;          /* 将s赋值给p的后继 */  
  173.     return OK;  
  174. }  
  175.   
  176. /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */  
  177. /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */  
  178. Status ListDelete(LinkList *L,int i,ElemType *e)  
  179. {  
  180.     int j;  
  181.     LinkList p,q;  
  182.     p = *L;  
  183.     j = 1;  
  184.     while (p->next && j < i)  /* 遍历寻找第i个元素 */  
  185.     {  
  186.         p = p->next;  
  187.         ++j;  
  188.     }  
  189.     if (!(p->next) || j > i)  
  190.         return ERROR;           /* 第i个元素不存在 */  
  191.     q = p->next;  
  192.     p->next = q->next;            /* 将q的后继赋值给p的后继 */  
  193.     *e = q->data;               /* 将q结点中的数据给e */  
  194.     free(q);                    /* 让系统回收此结点,释放内存 */  
  195.     return OK;  
  196. }  
  197.   
  198. /* 单链表反转/逆序 */  
  199. Status ListReverse(LinkList L)  
  200. {  
  201.     LinkList current,pnext,prev;  
  202.     if(L == NULL || L->next == NULL)  
  203.         return L;  
  204.     current = L->next;  /* p1指向链表头节点的下一个节点 */  
  205.     pnext = current->next;  
  206.     current->next = NULL;  
  207.     while(pnext)  
  208.     {  
  209.         prev = pnext->next;  
  210.         pnext->next = current;  
  211.         current = pnext;  
  212.         pnext = prev;  
  213.     }  
  214.     //printf("current = %d,next = %d \n",current->data,current->next->data);  
  215.     L->next = current;  /* 将链表头节点指向p1 */  
  216.     return L;  
  217. }  
  218.   
  219. Status ListReverse2(LinkList L)  
  220. {  
  221.     LinkList current, p;  
  222.   
  223.     if (L == NULL)  
  224.     {  
  225.         return NULL;  
  226.     }  
  227.     current = L->next;  
  228.     while (current->next != NULL)  
  229.     {  
  230.         p = current->next;  
  231.         current->next = p->next;  
  232.         p->next = L->next;  
  233.         L->next = p;  
  234.         ListTraverse(L);  
  235.         printf("current = %d, \n", current -> data);  
  236.     }  
  237.     return L;  
  238. }  
  239.   
  240. int main()  
  241. {  
  242.     LinkList L;  
  243.     Status i;  
  244.     int j,k,pos,value;  
  245.     char opp;  
  246.     ElemType e;  
  247.   
  248.     i=InitList(&L);  
  249.     printf("链表L初始化完毕,ListLength(L)=%d\n",ListLength(L));  
  250.   
  251.     printf("\n1.整表创建(头插法) \n2.整表创建(尾插法) \n3.遍历操作 \n4.插入操作");  
  252.     printf("\n5.删除操作 \n6.获取结点数据 \n7.查找某个数是否在链表中 \n8.置空链表");  
  253.     printf("\n9.链表反转逆序");  
  254.     printf("\n0.退出 \n请选择你的操作:\n");  
  255.     while(opp != '0'){  
  256.         scanf("%c",&opp);  
  257.         switch(opp){  
  258.             case '1':  
  259.                 CreateListHead(&L,10);  
  260.                 printf("整体创建L的元素(头插法):\n");  
  261.                 ListTraverse(L);  
  262.                 printf("\n");  
  263.                 break;  
  264.   
  265.             case '2':  
  266.                 CreateListTail(&L,10);  
  267.                 printf("整体创建L的元素(尾插法):\n");  
  268.                 ListTraverse(L);  
  269.                 printf("\n");  
  270.                 break;  
  271.   
  272.             case '3':  
  273.                 ListTraverse(L);  
  274.                 printf("\n");  
  275.                 break;  
  276.   
  277.             case '4':  
  278.                 printf("要在第几个位置插入元素?");  
  279.                 scanf("%d",&pos);  
  280.                 printf("插入的元素值是多少?");  
  281.                 scanf("%d",&value);  
  282.                 ListInsert(&L,pos,value);  
  283.                 ListTraverse(L);  
  284.                 printf("\n");  
  285.                 break;  
  286.   
  287.             case '5':  
  288.                 printf("要删除第几个元素?");  
  289.                 scanf("%d",&pos);  
  290.                 ListDelete(&L,pos,&e);  
  291.                 printf("删除第%d个元素成功,现在链表为:\n", pos);  
  292.                 ListTraverse(L);  
  293.                 printf("\n");  
  294.                 break;  
  295.   
  296.             case '6':  
  297.                 printf("你需要获取第几个元素?");  
  298.                 scanf("%d",&pos);  
  299.                 GetElem(L,pos,&e);  
  300.                 printf("第%d个元素的值为:%d\n", pos, e);  
  301.                 printf("\n");  
  302.                 break;  
  303.   
  304.             case '7':  
  305.                 printf("输入你需要查找的数:");  
  306.                 scanf("%d",&pos);  
  307.                 k=LocateElem(L,pos);  
  308.                 if(k)  
  309.                     printf("第%d个元素的值为%d\n",k,pos);  
  310.                 else  
  311.                     printf("没有值为%d的元素\n",pos);  
  312.                 printf("\n");  
  313.                 break;  
  314.   
  315.             case '8':  
  316.                 i=ClearList(&L);  
  317.                 printf("\n清空L后:ListLength(L)=%d\n",ListLength(L));  
  318.                 ListTraverse(L);  
  319.                 printf("\n");  
  320.                 break;  
  321.   
  322.             case '9':  
  323.                 ListReverse2(L);  
  324.                 printf("\n反转L后\n");  
  325.                 ListTraverse(L);  
  326.                 printf("\n");  
  327.                 break;  
  328.   
  329.             case '0':  
  330.                 exit(0);  
  331.         }  
  332.     }  
  333.   
  334. }  
#include "stdio.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 20 /* 存储空间初始分配量 */

typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */

typedef struct Node
{
    ElemType data;
    struct Node *next;
}Node;
/* 定义LinkList */
typedef struct Node *LinkList;

/* 初始化顺序线性表 */
Status InitList(LinkList *L)
{
    *L=(LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */
    if(!(*L)) /* 存储分配失败 */
    {
        return ERROR;
    }
    (*L)->next=NULL; /* 指针域为空 */

    return OK;
}

/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(LinkList L)
{
    int i=0;
    LinkList p=L->next; /* p指向第一个结点 */
    while(p)
    {
        i++;
        p=p->next;
    }
    return i;
}

/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(LinkList *L)
{
	LinkList p,q;
	p=(*L)->next;           /*  p指向第一个结点 */
	while(p)                /*  没到表尾 */
	{
		q=p->next;
		free(p);
		p=q;
	}
	(*L)->next=NULL;        /* 头结点指针域为空 */
	return OK;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(LinkList L)
{
    LinkList p=L->next;
    while(p)
    {
        visit(p->data);
        p=p->next;
    }
    printf("\n");
    return OK;
}

Status visit(ElemType c)
{
    printf("-> %d ",c);
    return OK;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
Status GetElem(LinkList L,int i,ElemType *e)
{
	int j;
	LinkList p;		/* 声明一结点p */
	p = L->next;		/* 让p指向链表L的第一个结点 */
	j = 1;		/*  j为计数器 */
	while (p && j < i)  /* p不为空或者计数器j还没有等于i时,循环继续 */
	{
		p = p->next;  /* 让p指向下一个结点 */
		++j;
	}
	if ( !p || j>i )
		return ERROR;  /*  第i个元素不存在 */
	*e = p->data;   /*  取第i个元素的数据 */
	return OK;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(LinkList L,ElemType e)
{
    int i=0;
    LinkList p=L->next;
    while(p)
    {
        i++;
        if(p->data==e) /* 找到这样的数据元素 */
                return i;
        p=p->next;
    }

    return 0;
}

/*  随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */
void CreateListHead(LinkList *L, int n)
{
	LinkList p;
	int i;
	srand(time(0));                         /* 初始化随机数种子 */
	*L = (LinkList)malloc(sizeof(Node));
	(*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */
	for (i=0; i < n; i++)
	{
		p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */
		p->data = rand()%100+1;             /*  随机生成100以内的数字 */
		p->next = (*L)->next;
		(*L)->next = p;						/*  插入到表头 */
	}
}

/*  随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */
void CreateListTail(LinkList *L, int n)
{
	LinkList p,r;
	int i;
	srand(time(0));                      /* 初始化随机数种子 */
	*L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */
	r=*L;                                /* r为指向尾部的结点 */
	for (i=0; i < n; i++)
	{
		p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */
		p->data = rand()%100+1;           /*  随机生成100以内的数字 */
		r->next=p;                        /* 将表尾终端结点的指针指向新结点 */
		r = p;                            /* 将当前的新结点定义为表尾终端结点 */
	}
	r->next = NULL;                       /* 表示当前链表结束 */
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(LinkList *L,int i,ElemType e)
{
	int j;
	LinkList p,s;
	p = *L;     /* 声明一个结点 p,指向头结点 */
	j = 1;
	while (p && j < i)     /* 寻找第i个结点 */
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return ERROR;   /* 第i个元素不存在 */
	s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */
	s->data = e;
	s->next = p->next;      /* 将p的后继结点赋值给s的后继  */
	p->next = s;          /* 将s赋值给p的后继 */
	return OK;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(LinkList *L,int i,ElemType *e)
{
	int j;
	LinkList p,q;
	p = *L;
	j = 1;
	while (p->next && j < i)	/* 遍历寻找第i个元素 */
	{
        p = p->next;
        ++j;
	}
	if (!(p->next) || j > i)
	    return ERROR;           /* 第i个元素不存在 */
	q = p->next;
	p->next = q->next;			/* 将q的后继赋值给p的后继 */
	*e = q->data;               /* 将q结点中的数据给e */
	free(q);                    /* 让系统回收此结点,释放内存 */
	return OK;
}

/* 单链表反转/逆序 */
Status ListReverse(LinkList L)
{
    LinkList current,pnext,prev;
    if(L == NULL || L->next == NULL)
        return L;
    current = L->next;  /* p1指向链表头节点的下一个节点 */
    pnext = current->next;
    current->next = NULL;
    while(pnext)
    {
        prev = pnext->next;
        pnext->next = current;
        current = pnext;
        pnext = prev;
    }
    //printf("current = %d,next = %d \n",current->data,current->next->data);
    L->next = current;  /* 将链表头节点指向p1 */
    return L;
}

Status ListReverse2(LinkList L)
{
    LinkList current, p;

    if (L == NULL)
    {
        return NULL;
    }
    current = L->next;
    while (current->next != NULL)
    {
        p = current->next;
        current->next = p->next;
        p->next = L->next;
        L->next = p;
        ListTraverse(L);
        printf("current = %d, \n", current -> data);
    }
    return L;
}

int main()
{
    LinkList L;
    Status i;
    int j,k,pos,value;
    char opp;
    ElemType e;

    i=InitList(&L);
    printf("链表L初始化完毕,ListLength(L)=%d\n",ListLength(L));

    printf("\n1.整表创建(头插法) \n2.整表创建(尾插法) \n3.遍历操作 \n4.插入操作");
    printf("\n5.删除操作 \n6.获取结点数据 \n7.查找某个数是否在链表中 \n8.置空链表");
    printf("\n9.链表反转逆序");
    printf("\n0.退出 \n请选择你的操作:\n");
    while(opp != '0'){
        scanf("%c",&opp);
        switch(opp){
            case '1':
                CreateListHead(&L,10);
                printf("整体创建L的元素(头插法):\n");
                ListTraverse(L);
                printf("\n");
                break;

            case '2':
                CreateListTail(&L,10);
                printf("整体创建L的元素(尾插法):\n");
                ListTraverse(L);
                printf("\n");
                break;

            case '3':
                ListTraverse(L);
                printf("\n");
                break;

            case '4':
                printf("要在第几个位置插入元素?");
                scanf("%d",&pos);
                printf("插入的元素值是多少?");
                scanf("%d",&value);
                ListInsert(&L,pos,value);
                ListTraverse(L);
                printf("\n");
                break;

            case '5':
                printf("要删除第几个元素?");
                scanf("%d",&pos);
                ListDelete(&L,pos,&e);
                printf("删除第%d个元素成功,现在链表为:\n", pos);
                ListTraverse(L);
                printf("\n");
                break;

            case '6':
                printf("你需要获取第几个元素?");
                scanf("%d",&pos);
                GetElem(L,pos,&e);
                printf("第%d个元素的值为:%d\n", pos, e);
                printf("\n");
                break;

            case '7':
                printf("输入你需要查找的数:");
                scanf("%d",&pos);
                k=LocateElem(L,pos);
                if(k)
                    printf("第%d个元素的值为%d\n",k,pos);
                else
                    printf("没有值为%d的元素\n",pos);
                printf("\n");
                break;

            case '8':
                i=ClearList(&L);
                printf("\n清空L后:ListLength(L)=%d\n",ListLength(L));
                ListTraverse(L);
                printf("\n");
                break;

            case '9':
                ListReverse2(L);
                printf("\n反转L后\n");
                ListTraverse(L);
                printf("\n");
                break;

            case '0':
                exit(0);
        }
    }

}



  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值