当前位置:  编程技术>c/c++/嵌入式

C语言单循环链表的表示与实现实例详解

    来源: 互联网  发布时间:2014-10-25

    本文导语:  1.概述: 对于一个循环链表来说,其首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。再来看另一种方法...

1.概述:

对于一个循环链表来说,其首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。再来看另一种方法,循环链表可以被视为“无头无尾”。这种列表很利于节约数据存储缓存, 假定你在一个列表中有一个对象并且希望所有其他对象迭代在一个非特殊的排列下。

指向整个列表的指针可以被称作访问指针。


用单向链表构建的循环链表

循环链表中第一个节点之前就是最后一个节点,反之亦然。循环链表的无边界使得在这样的链表上设计算法会比普通链表更加容易。对于新加入的节点应该是在第一个节点之前还是最后一个节点之后可以根据实际要求灵活处理,区别不大(详见下面实例代码)。当然,如果只会在最后插入数据(或者只会在之前),处理也是很容易的。
另外有一种模拟的循环链表,就是在访问到最后一个节点之后的时候,手工的跳转到第一个节点。访问到第一个节点之前的时候也一样。这样也可以实现循环链表的功能,在直接用循环链表比较麻烦或者可能会出现问题的时候可以用。

2.程序实现:

/* c2-2.h 线性表的单链表存储结构 */
 struct LNode
 {
  ElemType data;
  struct LNode *next;
 };
 typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */

/* bo2-4.c 设立尾指针的单循环链表(存储结构由c2-2.h定义)的12个基本操作 */
 Status InitList_CL(LinkList *L)
 { /* 操作结果:构造一个空的线性表L */
  *L=(LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
  if(!*L) /* 存储分配失败 */
   exit(OVERFLOW);
  (*L)->next=*L; /* 指针域指向头结点 */
  return OK;
 }
 Status DestroyList_CL(LinkList *L)
 { /* 操作结果:销毁线性表L */
  LinkList q,p=(*L)->next; /* p指向头结点 */
  while(p!=*L) /* 没到表尾 */
  {
   q=p->next;
   free(p);
   p=q;
  }
  free(*L);
  *L=NULL;
  return OK;
 }
 Status ClearList_CL(LinkList *L) /* 改变L */
 { /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
  LinkList p,q;
  *L=(*L)->next; /* L指向头结点 */
  p=(*L)->next; /* p指向第一个结点 */
  while(p!=*L) /* 没到表尾 */
  {
   q=p->next;
   free(p);
   p=q;
  }
  (*L)->next=*L; /* 头结点指针域指向自身 */
  return OK;
 }
 Status ListEmpty_CL(LinkList L)
 { /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
  if(L->next==L) /* 空 */
   return TRUE;
  else
   return FALSE;
 }
 int ListLength_CL(LinkList L)
 { /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */
  int i=0;
  LinkList p=L->next; /* p指向头结点 */
  while(p!=L) /* 没到表尾 */
  {
   i++;
   p=p->next;
  }
  return i;
 }
 Status GetElem_CL(LinkList L,int i,ElemType *e)
 { /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
  int j=1; /* 初始化,j为计数器 */
  LinkList p=L->next->next; /* p指向第一个结点 */
  if(iListLength_CL(L)) /* 第i个元素不存在 */
   return ERROR;
  while(jnext;
   j++;
  }
  *e=p->data; /* 取第i个元素 */
  return OK;
 }
 int LocateElem_CL(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
 { /* 初始条件:线性表L已存在,compare()是数据元素判定函数 */
  /* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
  /*      若这样的数据元素不存在,则返回值为0 */
  int i=0;
  LinkList p=L->next->next; /* p指向第一个结点 */
  while(p!=L->next)
  {
   i++;
   if(compare(p->data,e)) /* 满足关系 */
    return i;
   p=p->next;
  }
  return 0;
 }
 Status PriorElem_CL(LinkList L,ElemType cur_e,ElemType *pre_e)
 { /* 初始条件:线性表L已存在 */
  /* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
  /*      否则操作失败,pre_e无定义 */
  LinkList q,p=L->next->next; /* p指向第一个结点 */
  q=p->next;
  while(q!=L->next) /* p没到表尾 */
  {
   if(q->data==cur_e)
   {
    *pre_e=p->data;
    return TRUE;
   }
   p=q;
   q=q->next;
  }
  return FALSE;
 }
 Status NextElem_CL(LinkList L,ElemType cur_e,ElemType *next_e)
 { /* 初始条件:线性表L已存在 */
  /* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
  /*      否则操作失败,next_e无定义 */
  LinkList p=L->next->next; /* p指向第一个结点 */
  while(p!=L) /* p没到表尾 */
  {
   if(p->data==cur_e)
   {
    *next_e=p->next->data;
    return TRUE;
   }
   p=p->next;
  }
  return FALSE;
 }
 Status ListInsert_CL(LinkList *L,int i,ElemType e) /* 改变L */
 { /* 在L的第i个位置之前插入元素e */
  LinkList p=(*L)->next,s; /* p指向头结点 */
  int j=0;
  if(iListLength_CL(*L)+1) /* 无法在第i个元素之前插入 */
   return ERROR;
  while(jnext;
   j++;
  }
  s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
  s->data=e; /* 插入L中 */
  s->next=p->next;
  p->next=s;
  if(p==*L) /* 改变尾结点 */
   *L=s;
  return OK;
 }
 Status ListDelete_CL(LinkList *L,int i,ElemType *e) /* 改变L */
 { /* 删除L的第i个元素,并由e返回其值 */
  LinkList p=(*L)->next,q; /* p指向头结点 */
  int j=0;
  if(iListLength_CL(*L)) /* 第i个元素不存在 */
   return ERROR;
  while(jnext;
   j++;
  }
  q=p->next; /* q指向待删除结点 */
  p->next=q->next;
  *e=q->data;
  if(*L==q) /* 删除的是表尾元素 */
   *L=p;
  free(q); /* 释放待删除结点 */
  return OK;
 }
 Status ListTraverse_CL(LinkList L,void(*vi)(ElemType))
 { /* 初始条件:L已存在。操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
  LinkList p=L->next->next;
  while(p!=L->next)
  {
   vi(p->data);
   p=p->next;
  }
  printf("n");
  return OK;
 }

/* main2-4.c 单循环链表,检验bo2-4.c的主程序 */
 #include"c1.h"
 typedef int ElemType;
 #include"c2-2.h"
 #include"bo2-4.c"
 Status compare(ElemType c1,ElemType c2)
 {
  if(c1==c2)
   return TRUE;
  else
   return FALSE;
 }
 void visit(ElemType c)
 {
  printf("%d ",c);
 }
 void main()
 {
  LinkList L;
  ElemType e;
  int j;
  Status i;
  i=InitList_CL(&L); /* 初始化单循环链表L */
  printf("初始化单循环链表L i=%d (1:初始化成功)n",i);
  i=ListEmpty_CL(L);
  printf("L是否空 i=%d(1:空 0:否)n",i);
  ListInsert_CL(&L,1,3); /* 在L中依次插入3,5 */
  ListInsert_CL(&L,2,5);
  i=GetElem_CL(L,1,&e);
  j=ListLength_CL(L);
  printf("L中数据元素个数=%d,第1个元素的值为%d。n",j,e);
  printf("L中的数据元素依次为:");
  ListTraverse_CL(L,visit);
  PriorElem_CL(L,5,&e); /* 求元素5的前驱 */
  printf("5前面的元素的值为%d。n",e);
  NextElem_CL(L,3,&e); /* 求元素3的后继 */
  printf("3后面的元素的值为%d。n",e);
  printf("L是否空 %d(1:空 0:否)n",ListEmpty_CL(L));
  j=LocateElem_CL(L,5,compare);
  if(j)
   printf("L的第%d个元素为5。n",j);
  else
   printf("不存在值为5的元素n");
  i=ListDelete_CL(&L,2,&e);
  printf("删除L的第2个元素:n");
  if(i)
  {
   printf("删除的元素值为%d,现在L中的数据元素依次为:",e);
   ListTraverse_CL(L,visit);
  }
  else
   printf("删除不成功!n");
  printf("清空L:%d(1: 成功)n",ClearList_CL(&L));
  printf("清空L后,L是否空:%d(1:空 0:否)n",ListEmpty_CL(L));
  printf("销毁L:%d(1: 成功)n",DestroyList_CL(&L));
 }

    
 
 

您可能感兴趣的文章:

  • sql语言中delete删除命令语句详解
  • 汇编语言rep movsd 的使用详解
  • 基于C语言fflush()函数的使用详解
  • c语言中位字段与结构联合的组合使用详解
  • C语言中堆空间的生成与释放详解
  • 深入c语言continue和break的区别详解
  • C语言中#define与typedef的互换细节详解
  • 基于C语言中段错误的问题详解
  • C语言循环队列的表示与实现实例详解
  • 关于c语言的一个小bug详解
  • C语言单链队列的表示与实现实例详解
  • Android笔记之:深入为从右向左语言定义复杂字串的详解
  • C语言中判断int,long型等变量是否赋值的方法详解
  • 关于C语言指针赋值的问题详解
  • C语言高斯消元法的使用详解
  • C语言栈的表示与实现实例详解
  • 深入C语言内存区域分配(进程的各个段)详解
  • c语言中 基于随机函数的使用详解
  • 深入分析C语言中结构体指针的定义与引用详解
  • C语言位图算法详解
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • HTML超文本标记语言教程及实例
  • LINUX 或者Windows 如何保证一个进程只有一个实例在运行?如果是C语言,JAVA语言开发,又怎么样保证?
  • 大家帮我推荐些在linux下用c语言对数据库操作编程的实例或资料吧!谢谢!
  • C语言构建动态数组完整实例
  • C语言实现堆排序的简单实例
  • C语言实现杨辉三角实例
  • c语言 字符串转大写的简单实例
  • C语言二维数组的处理实例
  • c语言如何实现只运行单个进程实例?
  • C语言中自动隐式转换与类型强制转换实例分析
  • C语言十进制转二进制代码实例
  • C语言变量类型与输出控制用法实例教程
  • C语言创建链表错误之通过指针参数申请动态内存实例分析
  • C语言的递归思想实例分析
  • C语言二叉树的非递归遍历实例分析
  • C语言中qsort函数用法实例小结
  • C语言程序,软定时器应用的实例
  • c语言全盘搜索指定文件的实例代码
  • C语言连续子向量的最大和及时间度量实例
  • C语言安全之数组长度与指针实例解析
  • C语言中的回调函数实例
  • 2013年7月和2013年8月编程语言排行榜
  • 如何在GTK2.0下实现国际化(语言选择根据自己设置的语言,不用系统的语言)
  • 2017 年热门编程语言排行榜出炉,你的语言上榜没?
  • C语言中有指针,因此C语言可以创建链表,那么Java语言没有指针,那Java是否可以创建链表呢?
  • 苹果OS X和IOS下最新编程语言swift介绍
  • 求助,在linux下,c语言和汇编语言的接口是什么?
  • c语言判断某一年是否为闰年的各种实现程序代码
  • C语言中间语言 CIL
  • PHP编程语言介绍及安装测试方法
  • 最近学JSP,苦于HTML语言和JAVA语言太差,请教推荐几本书,thanks.


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3