Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2794295
  • 博文数量: 471
  • 博客积分: 7081
  • 博客等级: 少将
  • 技术积分: 5369
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-04 21:55
文章分类

全部博文(471)

文章存档

2014年(90)

2013年(69)

2012年(312)

分类: C/C++

2012-06-23 16:48:20

头结点是在链表的开始结点之前附加一个结点。它具有两个优点:

1、由于开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作就和在表的其它位置上操作一致,无须进行特殊处理;

2、无论链表是否为空,其头指针都是指向头结点的非空指针(空表中头结点的指针域空),因此空表和非空表的处理也就统一了。

3、头结点数据域的阴影表示该部分不存储信息。在有的应用中可用于存放表长等附加信息。

 1、单链表的创建

注意:

  上述算法里,动态申请新结点空间时未加错误处理,这对申请空间极少的程序而言不会出问题。但在实用程序里,尤其是对空间需求较大的程序,凡是涉及动态申请空间,一定要加入错误处理以防系统无空间可供分配。

 

2、单链表的查找运算 

(1)按序号查找

   ① 链表不是随机存取结构,在链表中,即使知道被访问结点的序号i,也不能像顺序表中那样直接按序号i访问结点,而只能从链表的头指针出发,顺链域next逐个结点往下搜索,直至搜索到第i个结点为止。

   ② 查找的思想方法

     计数器j置为0后,扫描指针p指针从链表的头结点开始顺着链扫描。当p扫描下一个结点时,计数器j相应地加1。当j=i时,指针p所指的结点就是要找的第i个结点。而当p指针指为NULL且j≠i时,则表示找不到第i个结点。注意:头结点可看做是第0个结点。

   ③算法分析:

while语句的终止条件是搜索到表尾或者满足j≥i,其频度最多为i,它和被寻找的位置有关。在等概率假设下,平均时间复杂度为:O(n)。

(2)按值查找

   ①思想方法 

    从开始结点出发,顺着链逐个将结点的值和给定值key作比较,若有结点的值与key相等,则返回首次找到的其值为key的结点的存储位置;否则返回NULL。

   ②算法分析

     该算法的执行时间亦与输入实例中key的取值相关,其平均时间复杂度分析类似于按序号查找,为O(n)。

3.插入运算
(1)思想方法
     插入运算是将值为x的新结点插入到表的第i个结点的位置上,即插入到ai-1与ai之间。
 (2)算法分析
     算法的时间主要耗费在查找操作GetNode上,故时间复杂度亦为O(n)。

4.删除运算

(1)思想方法
     删除运算是将表的第i个结点删去。
具体步骤: 
   
 (1)找到ai-1的存储位置p(因为在单链表中结点ai的存储地址是在其直接前趋结点ai-1的指针域next中)
    (2)令p->next指向ai的直接后继结点(即把ai从链上摘下)
    (3)释放结点ai的空间,将其归还给"存储池"。
 
注意:
     设单链表的长度为n,则删去第i个结点仅当1≤i≤n时是合法的。
     当i=n+1时,虽然被删结点不存在,但其前趋结点却存在,它是终端结点。因此被删结点的直接前趋*p存在并不意味着被删结点就一定存在,仅当*p存在(即p!=NULL)且*p不是终端结点(即p->next!=NULL)时,才能确定被删结点存在。

(2)算法分析

     算法的时间复杂度也是O(n)。
     链表上实现的插入和删除运算,无须移动结点,仅需修改指针。
 

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<malloc.h>
  3. typedef char DataType;
  4. typedef struct node
  5.         {
  6.             DataType data;
  7.             struct node * next;
  8.         }ListNode;

  9. typedef struct node *LinkList;



  10. void print(LinkList head)
  11. {
  12.     LinkList p=head->next;
  13.     while(p)
  14.     {
  15.         printf("%c ",p->data);
  16.         p=p->next;
  17.     }
  18.     printf("\n");
  19. }

  20. /*
  21. **从开始结点出发,顺着链逐个将结点的值和给定值key作比较,
  22. **若有结点的值与key相等,则返回首次找到的其值为key的结点的存储位置;
  23. **否则返回NULL。
  24. */
  25. ListNode * getNodeByVal(LinkList head,char key)
  26. {
  27.     LinkList p=head->next;
  28.     while(p && p->data != key)
  29.     {
  30.         p=p->next;
  31.     }
  32.     return p;
  33. }

  34. /*
  35. **按序号查找,
  36. **在带头结点的单链表head中查找第i个结点,
  37. **若找到(0≤i≤n),0为头结点
  38. */
  39. ListNode * getNodeByNum(LinkList head,int i)
  40. {
  41.     int j;
  42.     ListNode * p;
  43.     p=head;
  44.     j=0;//从头结点开始扫描
  45.     while(p->next && j<i)
  46.     {
  47.         p=p->next;
  48.         j++;
  49.     }
  50.     if(i==j)
  51.         return p;
  52.     else
  53.         return NULL;//当传入的i <0 || i>n无效

  54. }

  55. /*
  56. **插入运算是将值为x的新结点插入到表的第i个结点的位置上,
  57. **即插入到ai-1与ai之间
  58. */
  59. ListNode * insertList(LinkList head,char x, int i)
  60. {
  61.     LinkList p=getNodeByNum(head,i-1);//寻找第i-1个结点
  62.     if(p==NULL)//i<1或i>n+1时插入位置i有错
  63.     {
  64.          printf("position error");
  65.     }
  66.     LinkList s=(ListNode *)malloc(sizeof(ListNode));
  67.     s->data=x;
  68.     s->next=p->next;
  69.     p->next=s;
  70.     return head;
  71. }
  72. /*
  73. **删除运算是将表的第i个结点删去
  74. **设单链表的长度为n,则删去第i个结点仅当1≤i≤n时是合法的。
  75. */
  76. LinkList delList(LinkList head,int i)
  77. {
  78.     LinkList p=getNodeByNum(head,i-1);//寻找第i-1个结点
  79.     if(p==NULL || p->next == NULL)//i<0或i=>n时删除位置i有错
  80.     {
  81.          printf("position error");
  82.     }
  83.     LinkList r=p->next;//r指向将要删除的节点
  84.     p->next = r->next;
  85.     free(r);
  86.     return head;
  87. }

  88. /*
  89. **尾插法创建带头结点链表
  90. */
  91. LinkList CreatListR(void)
  92. {
  93.     char ch;
  94.     LinkList head=(ListNode *)malloc(sizeof(ListNode));//生成头结点,可以存储一些信息
  95.     LinkList r,s;
  96.     r=head;
  97.     while(scanf("%c",&ch)!=EOF && ch!='0')
  98.     {
  99.         s =(ListNode *)malloc(sizeof(ListNode));
  100.         s->data=ch;
  101.         r->next=s;
  102.         r=s;
  103.     }
  104.     r->next=NULL;//终端结点的指针域置空,或空表的头结点指针域置空
  105.     return head;
  106. }

  107. int main()
  108. {
  109.     /*注意一下字符输入与整数吾同
  110.     abcdef0
  111.     dPress any key to continue*/
  112.     LinkList head=CreatListR();
  113.     LinkList NUM4=getNodeByNum(head,4);
  114.     printf("%c",NUM4->data);
  115.     
  116.     NUM4 = getNodeByVal(head,'d');
  117.     printf("\n%c",NUM4->data);

  118.     head=insertList(head,'e',5);
  119.     print(head);
  120.     head=delList(head,5);
  121.     print(head);
  122.     return 0;
  123. }

阅读(1064) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~