线性表的静态单链表存储结构
2016-05-20 20:04
309 查看
/* 借用一维数组来描述线性链表 —————— 线性表的静态单链表存储结构—————— #define MAXSIZE 1000 //链表的最大长度 typedef struct { ElemType data; int cur; }component,SLinkList[MAXSIZE]; 这种描述方法便于不设“指针”类型的高级程序设计语言中使用链表结构 如上描述的链表中,数组的一个分量表示一个结点,同时用游标(指示器cur)代替指针指示结点在数组中的相对位置 数组的第零分量可看成头结点,其指针域指示链表的第一个结点 这种存储结构仍需要预先分配一个较大的空间,但在线性链表的插入和删除操作时不需要移动元素, 仅需修改指针(cur),仍具有链式存储结构的优点,把这种用数组描述的链表起名叫 静态链表 */ #include <stdio.h> #define MAXSIZE 100 //链表的最大长度 typedef struct { int data; int cur; }component,SLinkList[MAXSIZE]; void InitList(SLinkList L); //构造一个空的链表 //以下两个函数被函数ListInsert()调用 int Malloc(SLinkList space); int ListLength(SLinkList L); //返回L中数据元素的个数 bool ListInsert(SLinkList L,int i,int e); //在L中第i个元素之前插入新的数据元素e bool ListTraverse(SLinkList L); //输出线性表的数据 void ListEmpty(SLinkList L); //判断线性表是否为空 bool ClearList(SLinkList L); //将L置为空表 bool GetElem(SLinkList L,int i,int *e); //用e返回L中第i元素的值 int LocateElem(SLinkList L,int e); bool PriorElem(SLinkList L,int cur_e,int *pre_e); bool NextElem(SLinkList L,int cur_e,int *next_e); void Free(SLinkList space,int k); bool ListDelete(SLinkList L,int i,int *e); int main() { int j, k; int e, e0; SLinkList L; InitList(L); for(j = 1; j <= 5; j++) ListInsert(L,1,j); printf("在L的表头依次插入1-5后:L = "); ListTraverse(L); ListEmpty(L); //判断L是否为空 printf("len = %d\n",ListLength(L)); ClearList(L); //清空链表 ListEmpty(L); //判断L是否为空 for(j = 1; j <= 10; j++) ListInsert(L,j,j); printf("在L的表中依次插入1-10后:L = "); ListTraverse(L); GetElem(L,5,&e);//把第5个元素赋给 e printf("第5个元素的值为:%d\n",e); for(j = 1; j <= 10; j++) { k = LocateElem(L,j); if(k) printf("值为%d的元素在静态链表中的位序为%d\n",j,k); else printf("没有值为%d的元素\n",j); } for(j = 1; j <= 2; j++) //测试头两个数据 { GetElem(L,j,&e0); //把第j个数据赋给e0 PriorElem(L,e0,&e); //求e0的前驱 if( PriorElem(L,e0,&e) ) printf("元素%d的前驱为:%d\n",e0,e); else printf("元素%d无前驱\n",e0); } for(j = ListLength(L) - 1; j <= ListLength(L); j++) //最后两个数据 { GetElem(L,j,&e0); //把第j个元素赋给e0; NextElem(L,e0,&e); //求e0的后继 if( NextElem(L,e0,&e) ) printf("元素%d的后继为:%d\n",e0,e); else printf("元素%d无后继\n",e0); } k = ListLength(L); //k为表长 ListDelete(L,k,&e); printf("删除的元素为: %d\n",e); ListDelete(L,k-1,&e); printf("删除的元素为: %d\n",e); printf("依次输出L的元素:"); ListTraverse(L); //输出元素的值 return 0; } void InitList(SLinkList L) //构造一个空的链表 { //表头为L的最后一个单元L[MAXSIZE-1] ,其余单元链成一个 //备用链表,表头为L的第一个单元L[0].cur, "0"表示空指针 int i; L[MAXSIZE-1].cur = 0; //L的最后一个单元为空链表的表头 for(i = 0; i < MAXSIZE - 2; i++) //将其余单元链接成以L[0]为表头的备用链表 L[i].cur = i + 1; L[MAXSIZE-2].cur = 0; } bool ListInsert(SLinkList L,int i,int e) //在L中第i个元素之前插入新的数据元素e { int l, j, k = MAXSIZE - 1; //k指向表头 if(i < 1 || i > ListLength(L) + 1) return false; j = Malloc(L); //申请新单元 if(j) //申请成功 { L[j].data = e; //赋值给新单元 for(l = 1; l < i; l++) //移动第i-1个元素 k = L[k].cur; L[j].cur = L[k].cur; L[k].cur = j; return true; } return false; } int ListLength(SLinkList L) //返回L中数据元素的个数 { int j = 0, i = L[MAXSIZE-1].cur; //i指向第一个元素 while(i) //没到静态链表尾 { i = L[i].cur; //指向下一个元素 j++; } return j; } int Malloc(SLinkList space) { //若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回 0 int i = space[0].cur; if(i) //备用链表非空 space[0].cur = space[i].cur; //备用链表的头节点指向原备用链表的第二个结点 return i; //返回 } bool ListTraverse(SLinkList L) //输出线性表的数据 { int i = L[MAXSIZE-1].cur; //指向第一个元素 while(i) //没有到静态链表尾 { printf("%d ",L[i].data); i = L[i].cur; //指向下一个元素 } printf("\n"); return true; } void ListEmpty(SLinkList L) //判断线性表是否为空 { if(L[MAXSIZE-1].cur == 0) //表为空 printf("链表为空\n"); else printf("链表不为空\n"); } bool ClearList(SLinkList L) //将L置为空表 { int i, j, k; i = L[MAXSIZE-1].cur; //链表第一个结点的位置 L[MAXSIZE-1].cur = 0; //链表空 k = L[0].cur; //备用链表第一个结点的位置 L[0].cur = i; // 把链表的结点连接到备用链表的表头 while(i) //没有到表尾 { j = i; i = L[i].cur; //指向下一个元素 } L[j].cur = k; //备用链表的第一个结点连接到链表的尾部 return true; } bool GetElem(SLinkList L,int i,int *e) //用e返回L中第i元素的值 { int l,k = MAXSIZE - 1; //K指向表头序号 if(i < 1|| i > ListLength(L)) return false; for(l = 1; l <= i; l++) //移动到第i个元素处 k = L[k].cur; *e = L[k].data; return true; } int LocateElem(SLinkList L,int e) { //在静态单链线性表L中查找第i个值为e的元素 若找到,则返回它在L中的位序 int i = L[MAXSIZE-1].cur; //i指示表中第一个结点 while(i && L[i].data != e) //在表中顺序查找 i = L[i].cur; return i; } bool PriorElem(SLinkList L,int cur_e,int *pre_e) { // 若cur_e是L的数据元素,且不是第一个 则用pre_e返回它的前驱 int j, i = L[MAXSIZE-1].cur; //i指示链表第一个结点的位置 do { //向后移动结点 j = i; i = L[i].cur; }while(i && cur_e != L[i].data); if(i) //找到该元素 { *pre_e = L[j].data; return true; } return false; } bool NextElem(SLinkList L,int cur_e,int *next_e) { //若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继 int j, i = LocateElem(L,cur_e); //在L中查找第一个值为cur_e元素的位置 if(i) //L中存在cur_e { j = L[i].cur; //cur_e的后继位置 if(j) //cur_e有后继 { *next_e = L[j].data; return true; //cur_e元素有后继 } } return false; } bool ListDelete(SLinkList L,int i,int *e) { //删除在L中第i个数据元素e 并返回其值 int j, k = MAXSIZE - 1; if(i < 1 || i > ListLength(L)) return false; for(j = 1; j < i; j++) //移动 i- 1 个元素 k = L[k].cur; j = L[k].cur; L[k].cur = L[j].cur; *e = L[j].data; Free(L,j); return true; } void Free(SLinkList space,int k) { //将下标为k的空闲结点回收到备用链表 space[k].cur = space[0].cur; //回收结点的“游标”指向备用链表的第一个结点 space[0].cur = k; //备用链表的头结点指向新的收点 }
程序执行结果:
相关文章推荐
- PowerDesigner 反向工程生成ER图步骤
- 实现strcpy的功能【不可以使用strcyp函数】
- Python os.popen()方法的用法
- 《链表》——单向链表和双向链表(Java)
- android开发步步为营之104:文字加阴影效果和描边效果的实现
- lightoj 1421 - Wavio Sequence LIS变形
- Max Factor (hdu_2710) 素数筛选
- 快速理解C#中的委托与事件
- 从开始到结束,手把手教你使用busybox构建类嵌入式Linux系统
- windows下vs2013使用C++访问redis
- Android 的Context和application
- java集合总结
- 你若顽强到底,一切皆有可能——谈工程师职业素养(《大话Java性能优化》前言)
- sdut 3257 Cube number
- 多线程技术(三)
- 【bzoj 2393】Cirno的完美算数教室
- HashMap和HashSet的区别
- 字典树典型应用(1247)
- const char **ptr 与 char *ptr[] 的释放问题的探究
- MySQL入门--显示指定数据表的字段结构、插入指定字段的值(记录)、查看指定表中指定字段的所有记录