Chinaunix首页 | 论坛 | 博客
  • 博客访问: 345047
  • 博文数量: 201
  • 博客积分: 305
  • 博客等级: 二等列兵
  • 技术积分: 500
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-30 16:58
文章分类

全部博文(201)

文章存档

2015年(5)

2014年(12)

2013年(173)

2012年(11)

我的朋友

分类: C/C++

2013-01-21 23:01:16

原文地址:数据结构之线性表(单链表) 作者:


  
1. 线性链表
  
   线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。这些数据元素可以存在内存未被占用的任意位置。
   它包括两个域:其中存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称为指针或链。
   由于此链表的每个结点中只包含一个指针域,故又称为线性链表或单链表。
   对于线性表来说,总得有个头有个尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行的。之后的每个结点,其实就是上一个后指针指向的位置。最后一个结点,意味着后继不再存在,所以,规定线性链表的最后一个结点指针为“空”(通常为NULL)。 

   线性表的单链表存储结构,如下所示。
  1. typedef struct Node
  2. {
  3.      ElemType data;
  4.      struct Node *next;
  5. }Node, LinkList;

2. 线性表的操作

  获取链表第i个数据的算法思路:

  1)声明一个结点p指向链表第一个结点,初始化j1开始;

  2)j时,就遍历链表,p的指针向后移动,不断指向下一个结点,j累加1

  3)若到链表末尾p为空,则说明第i个元素不存在;

  4)否则查找成功,返回结点p的数据。


  单链表第i个数据插入结点的算法思路:

  

  1)声明一个结点p指向链表的第一个结点,初始化j1开始;

  2)j时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1

  3)若到链表末尾p为空,则说明第i个元素不存在;

  4)否则查找成功,在系统中生成一个空结点s

  5)将数据元素e赋值给s->data

  6)单链表的插入标准语句s->next = p->nextp->next = s

  7)返回成功。


  单链表第i个数据删除结点的算法思路:

  

  1)声明一个结点p指向单链表的第一个结点,初始化j1开始;

  2)j时,就遍历链表,让p指针向后移动,不断指向下一个结点,j累加1

  3)若到链表末尾p为空,则说明第i个元素不存在;

  4)否则查找成功,将欲删除的结点p->next赋值给q

  5)单链表的删除标准语句p->next = q->next

  6)q结点中的数据赋值给e,作为返回;

  7)释放q结点。


  单链表的整表创建的算法思路:

  

  1)声明一个结点p和计数器变量i

  2)初始化一空链表L

  3)L的头结点的指针指向NULL,即建立一个带头结点的单链表;

  4)循环

生成一新结点赋值给p

随机生成一数字赋值给p的数据域p->data

p插入到头结点域前一新结点之间。


  单链表的整表删除的算法思路如下:

  

  1)声明一结点pq

  2)将第一个结点赋值给p

  3)循环:

将下一个结点赋值给q

释放p

q赋值给p


3. 线性表操作的C实现

  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. #define OK 0
  4. #define ERROR 1

  5. //typedef ElemType int;
  6. #define ElemType int
  7. typedef struct Node
  8. {
  9.     ElemType data;
  10.     struct Node *next;
  11. }Node, *LinkList;

  12. /* 函数功能:获取链表第i个数据
  13.  * 操作结果:用e返回L中第i个数据元素的值
  14.  * 返回值:
  15.  *         ERROR:i值不合法
  16.  *         OK     :操作成功
  17.  *
  18.  * 最坏时间复杂度为O(n)
  19. */
  20. int GetElem(LinkList L, int i, ElemType *e)
  21. {
  22.     if( i <= 0)
  23.     {
  24.         fprintf(stderr, "i should more 1 and less LinkLength(L).\n");
  25.         return ERROR;
  26.     }
  27.     LinkList p = L->next;            //声明一结点p
  28.     int j = 1;                        //j为计数器

  29.     while(j < i && p != NULL)        //p不为空且计数器j还没有等于i时,循环继续
  30.     {
  31.         p = p->next;
  32.         j++;
  33.     }

  34.     if(!p || j > i)                    //第i个元素不存在
  35.     {
  36.         return ERROR;
  37.     }

  38.     *e = p->data;

  39.     return OK;
  40. }


  41. /* 函数名称: ListInsert
  42.  * 函数功能: 在链表的第i个位置之前插入数据元素e
  43.  * 返回值:
  44.  *        ERROR: i不合法
  45.  *        OK : 插入成功
  46.  *
  47.  * 注意:参数L为指针的指针
  48. */

  49. int LinkInsert(LinkList *L, int i, ElemType e)
  50. {
  51.     if( i <= 0)
  52.     {
  53.         fprintf(stderr, "i<=0不合法.\n");
  54.         return ERROR;
  55.     }

  56.     LinkList p;
  57.     p = *L;
  58.     int j = 1;

  59.     while(j < i && p != NULL)            //寻找第i个结点
  60.     {
  61.         p = p->next;
  62.         ++j;
  63.     }

  64.     if(!p || j > i)                        //第i个结点不存在
  65.     {
  66.         return ERROR;
  67.     }

  68.     LinkList temp = (LinkList)malloc(sizeof(struct Node));
  69.     if(!temp)
  70.     {
  71.         fprintf(stderr, "malloc() error.\n");
  72.         return ERROR;
  73.     }

  74.     temp->data = e;

  75.     temp->next = p->next;
  76.     p->next = temp;

  77.     return OK;
  78. }

  79. /* 函数名称: ListDelete
  80.  * 函数功能: 删除L中的第i个元素,并用e返回其值
  81.  * 返回值:
  82.  *        ERROR: i不合法
  83.  *        OK : 删除成功
  84.  *
  85.  * 最坏时间复杂度为O(n)
  86. */
  87. int ListDelete(LinkList *L, int i, ElemType *e)
  88. {
  89.     if(i <= 0)
  90.     {
  91.         fprintf(stderr, "i <= 0不合法.\n");
  92.         return ERROR;
  93.     }

  94.     LinkList p,q;
  95.     p = *L;
  96.     int j = 1;

  97.     while(j < i && p->next != NULL)        //遍历寻找第i个结点
  98.     {
  99.         p = p->next;
  100.         ++j;
  101.     }

  102.     if(p->next == NULL || j > i)
  103.     {
  104.         return ERROR;
  105.     }

  106.     q = p->next;
  107.     p->next = q->next;
  108.     *e = q->data;

  109.     free(q);
  110.     
  111.     return OK;
  112. }

  113. /* 函数名称: CreateList
  114.  * 函数功能: 随机产生n个元素的值,建立带头结点的单链表L(头插法)
  115.  * 返回值:
  116.  *        ERROR: malloc() error
  117.  *        OK : 创建成功
  118.  *
  119.  */
  120. int CreateList(LinkList *L, int n)
  121. {
  122.     LinkList p;
  123.     int i = 1;
  124.     srand(time(0));                                    //初始化随机数种子

  125.     *L = (LinkList)malloc(sizeof(struct Node));        //先建立一个带头结点的单链表
  126.     if(*L == NULL)
  127.     {
  128.         fprintf(stderr, "malloc() error.\n");
  129.         return ERROR;
  130.     }
  131.     (*L)->next = NULL;

  132.     while(i <= n)
  133.     {
  134.         p = (LinkList)malloc(sizeof(struct Node));
  135.         if( p == NULL)
  136.         {
  137.             fprintf(stderr, "malloc() error.\n");
  138.             return ERROR;
  139.         }
  140.         p->data = rand() % 100 + 1;
  141.         p->next = (*L)->next;
  142.         (*L)->next = p;                                    //插入到表头
  143.         
  144.         i++;
  145.     }
  146.     /*
  147.     //尾插法
  148.     LinkList r;
  149.     r = *L;                                                //r为指向尾部的结点
  150.     for(i = 0; i < n; i++)
  151.     {
  152.         p = (LinkList)malloc(sizeof(struct Node));        //生成新结点
  153.         p->data = rand() % 100 + 1;
  154.         r->next = p;                                    //将表尾终端结点的指针指向新结点
  155.         r = p;                                            //将当前的新结点定义为表尾部结点
  156.     }
  157.     r->next = NULL;                                        //表示当前链表结束
  158.     */
  159.     return OK;
  160. }

  161. /* 函数名称: ClearList
  162.  * 函数功能: 单链表删除
  163. */
  164. int ClearList(LinkList *L)
  165. {
  166.     if(*L == NULL)
  167.     {
  168.         return ERROR;
  169.     }

  170.     LinkList q, p;
  171.     p = (*L)->next;        //p指向第一个结点

  172.     while(p)            //没有到表尾部
  173.     {
  174.         q = p->next;    //注意哦
  175.         free(p);
  176.         p = q;
  177.     }

  178.     (*L)->next = NULL;    //头结点指针域为空

  179.     return OK;
  180. }

  181. int printList(LinkList L)
  182. {
  183.     LinkList p;
  184.     p = L->next;
  185.     if(p == NULL)
  186.     {
  187.         printf("链表为空.\n");
  188.         return ERROR;
  189.     }
  190.     while(p)
  191.     {
  192.         printf("%d ", p->data);
  193.         p = p->next;
  194.     }
  195.     printf("\n");

  196.     return OK;
  197. }

  198. int main(int argc, char **argv)
  199. {
  200.     LinkList L;
  201.     
  202.     printf("创建的新链表为:\n");
  203.     CreateList(&L, 5);
  204.     printList(L);
  205.     
  206.     printf("在第3个位置之前插入元素10后结果为:\n");
  207.     LinkInsert(&L, 3, 10);
  208.     printList(L);

  209.     int e;
  210.     GetElem(L, 3, &e);     
  211.     printf("链表第3个位置的元素为: %d\n", e);
  212.     
  213.     printf("删除第3个位置的元素后结果为:\n");
  214.     ListDelete(&L, 3, &e);
  215.     printList(L);
  216.     
  217.     printf("清空链表:\n");
  218.     ClearList(&L);
  219.     printList(L);
  220.     
  221.     return 0;
  222. }
   运行环境:RedHat
   编译工具:Gcc
   
   运行结果如下所示:




    参考:严蔚敏老师之《数据结构》


                                                                                                                                                          梦醒潇湘love
                                                                                                                                                      2013-01-08 20:30
阅读(430) | 评论(0) | 转发(0) |
0

上一篇:vim

下一篇:数据结构之栈

给主人留下些什么吧!~~