c语言结构体单链表转换结构体数组,c语言数据结构,静态链表,结构体数组

众所周知,我的博客是写给自己看的。

在敲"严版"数据结构的静态数组时遇到的一些问题,并给予了改进,在此记录一下

前言:

没有实现教材上那个(A-B)v(B-A)的例子,实现了增加、删除等。总体上把握了静态数组的基本思想后实现这些例子都是很简单的。作了一点小改进

正文:

改进:

09f41c036cf202cd4dbed9ff38280e44.png

把一个静态数组分为两条形式上的链表,一条是已分配空间,一条是未分配的空间。从尾部开始,链表的头标记为arr[10].cur遍历可获得A-B-C-D,arr[10].data为已分配结点的数量;arr[0].cur是未分配空间的头标记,arr[0].data为未分配结点的数量;插入一个结点就把可用空间的结点通过改变cur来实现连接,删除也是同样的思想。

静态数组,其实就是顺序表。依靠结构体成员,像链表一样把不同的空间连起来,只不过把指针类型的成员变量用int类型代替。

下面是结构体:

1 int LISTSIZE = 100;2 typedef intElemType;3 typedef structSLinkList {4 ElemType data;5 intcur;6 } SLinkList;

// 不建议

1 intLISTSIZE= 100;

2 typedef intElemType;

3 typedef structSLinkList {

4 ElemType data;

5 intcur;

6} SLinkList[LISTSIZE];

1)、设置一个全局变量LISTSIZE代替书上的宏变量,方便在数组空间不够用的情况下新增空间

2)、typedef这个结构体变量名为SLlinkList。如果你typedef这个结构体变量为SLinkList[LISTSIZE]要注意了,这样做有许多的缺点,会让你走许多的弯路。

1.减少了灵活性,声明这个变量SLinkList L;这样就固定了100个空间的大小,你想申请200是不可能的;而typedef为SLinkList,声明这个变量时SLinkList L[345];这样是很灵活的。

2.把访问结构体成员弄得很复杂,熟悉c就会知道指针需要用"->"访问、变量需要用"."访问,通过形参传地址修改必须要用*p。而c基础不过关的(比如说我)就会犯错误如结构体声明为typedef SLinkList[100]; SLinkList L; L[i]->data;这样访问,这是错误的访问方法,除了静态数组第一个也就是L[0]可以修改外,其他元素修改不了。正确的访问方式是先*L访问首地址,然后(*L+i)加上偏移量找到指定空间,这是一个指针,然后(*L+i)->data这才是正确的访问方式。

分配地址空间:malloc分配或者变量自动分配

1 SLinkList *L = (SLinkList *)malloc(sizeof(SLinkList) *LISTSIZE);2 或者3 SLinkList L[LISTSIZE];

代码:

1 #include

2 #include

3 #include

4 #include "..custom.h"

5 #include "..est.c"

6

7 /**8 * 静态链表,使用index的相对位置作为指针,方便在不设指针类型的程序中使用链表结构9 * 预先需要分配较大的数组空间10 * 说白了就是链表,只不过是片连续的地址空间11 */

12 int LISTSIZE = 100;13 typedef intElemType;14 typedef structSLinkList {15 ElemType data;16 intcur;17 } SLinkList;18

19 /**20 * 初始化21 */

22 void initSLinkList(SLinkList *L) {23 //L[0]->data保存未分配数组的长度,不包括第一个和最后一个

24 for (int i = 0; i < LISTSIZE - 1; i++) {25 L[i].cur = i + 1;26 }27 L[0].data = LISTSIZE - 2;28 //L[LISTSIZE].cur分配了的结点的首地址,L[LISTSIZE].data保存分配了的长度

29 L[LISTSIZE - 1].cur = 0;30 L[LISTSIZE - 1].data = 0;31 }32

33 /**34 * 遍历L35 */

36 void traverseSLinkList(SLinkList *L) {37 if (L[LISTSIZE - 1].data == 0) return;38 int i = L[LISTSIZE - 1].cur;39 while (i != 0) {40 printf("%d", L[i].data);41 i = L[i].cur; //类似于p=p->next

42 }43 printf("");44 }45

46 /**47 * 在第i个位置插入e48 */

49 int listInsert(SLinkList *L, inti, ElemType e) {50 if (L[0].data == 0) {51 //L[0].data==0表明未分配的空间已经用完,重新分配一个空间

52 printf("空间不足");53 return 0;54 }55 if (i > L[LISTSIZE - 1].data + 1) {56 printf("位置i不合法");57 return 0;58 }59 //在未分配空间的L拿出一个空间来, 就拿第一个

60 int index = L[0].cur;61 L[0].cur =L[index].cur;62

63 L[index].data = e; //为这个空间赋值64

65 //找已分配链表的第i个位置

66 int k = LISTSIZE - 1;67 for (int j = 0; j < i; j++) {68 k =L[k].cur;69 }70 L[index].cur = L[k].cur; //连接

71 L[k].cur =index;72

73 L[0].data--; //用掉一个结点

74 L[LISTSIZE - 1].data++; //增加一个分配了的结点

75 return 1;76 }77

78 /**79 * 删除一个元素80 */

81 int listDelete(SLinkList *L, int i, ElemType *e) {82 if (L[LISTSIZE - 1].data == 0) return 0;83 //找到第i个位置

84 int k = LISTSIZE - 1;85 for (int j = 0; j < i; j++) {86 k =L[k].cur;87 }88 int index =L[k].cur;89 L[k].cur =L[index].cur;90

91 *e = L[index].data; //赋值92

93 //加入空闲的链表

94 L[index].cur = L[0].cur;95 L[0].cur =index;96

97 L[0].data++; //增加一个未分配结点

98 L[LISTSIZE - 1].data--; //减少一个分配了的结点

99 return 1;100 }101

102 /**103 * 测试104 */

105 void createList(SLinkList *L) {106 initSLinkList(L);107 for (int i = 0; i < 10; i++) {108 listInsert(L, i, i * 111);109 }110 }111 intmain() {112 SLinkList *L = (SLinkList *)malloc(sizeof(SLinkList) *LISTSIZE);113 createList(L);114 traverseSLinkList(L);115 printf("空间总长度%d", LISTSIZE);116 printf("已用空间长度%d", L[LISTSIZE - 1].data);117 printf("未用空间长度%d", L[0].data);118 ElemType e;119 listDelete(L, 2, &e);120 printf("e:%d", e);121 listInsert(L, 1, 5);122 traverseSLinkList(L);123 printf("空间总长度%d", LISTSIZE);124 printf("已用空间长度%d", L[LISTSIZE - 1].data);125 printf("未用空间长度%d", L[0].data);126 return 0;127 }

总结:

其它的就难得写了,静态数组思想大概就是这样。"严版"数据结构书上这一节写得云里雾里的,不仔细看和操练不容易搞出来。

注意声明结构体数组不同,引用结构体成员的方式也不同;

在懂得算法思想的基础上改进、创新代码。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值