(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
目录
(本章与之前的链表知识有些不同,理解起来可能有些困难(我花了好久才理解),如果看完后有困惑,欢迎私信一起讨论)
初识静态链表:
用数组描述的链表,即为静态链表
在c语言中,静态链表的表现形式即为结构体数组
结构体变量包括数据域data和游标next
优点:在插入时只需要修改游标,不需要移动元素
#define MAX_SIZE_SSL 10 typedef struct { int id; char* name; }ElementType; /** 静态链表-就是一个结构数组 */ typedef struct { ElementType data; //数据域 int next; //int cursor; 游标,如果为0表示无指向 }StaticLinkList[MAX_SIZE_SSL];
初始化:
每个元素的游标指向下一个元素
数组的最后一个元素next用来保存第一个插入元素的下标,最后一个元素初始为0
第一个元素的next用来存放第一个空闲结点的下标
因此,数组的第一个和最后一个元素不属于数据域范围,所以当倒数第二个元素指向最后一个元素时,实际上指向为0
/** 初始化链表 */ void InitStaticLinkList(StaticLinkList slList) { for (int i = 0; i < MAX_SIZE_SSL; i++) { slList[i].next = i + 1;//游标指向下一个 } //将最后一个结点置空 slList[MAX_SIZE_SSL - 1].next = 0; //将备用链表的尾结点(倒数第二个元素)置为空 slList[MAX_SIZE_SSL - 2].next = 0; }
静态链表的插入:
第一个元素的next用来存放第一个空闲结点的下标,当数组下标为1的结点插入数据后,第一个元素的next就改为2(即下一个空闲结点的下标),同时将刚插入数据的元素的next改为0(这里有些难以理解,请大家结合图例)
初始化时:
在数组下标为1的位置插入数据后 :
数据一直插入到下标为4的位置后 :
/** 向指定位置插入元素 */ int InsertStaticLinkList(StaticLinkList slList, int pos, ElementType element) { if (pos < 1 || pos > GetStaticLinkList(slList) + 1) { return 0; } int cursor = MAX_SIZE_SSL - 1; //拿到第一个元素的下标 //需要判断cursor的范围是否合法 //分配内存 int newIndex = mallocSSL(slList);//待插入结点的下标 if (newIndex) { slList[newIndex].data = element; //找到newIndex的前缀结点 for (int i = 1; i <= pos - 1; i++) { cursor = slList[cursor].next; } slList[newIndex].next = slList[cursor].next; slList[cursor].next = newIndex;//使前缀结点的next指向newIndex return 1; } return 0; } /** 为静态链表分配一个空间的内存,返回0表示分配失败 */ int mallocSSL(StaticLinkList slList) { //拿到第一个空闲结点下标(备用链表)下标 int cursor = slList[0].next; //将该下标改为下一个空闲结点的下标 if (cursor) { slList[0].next = slList[cursor].next; } return cursor; }
获得静态链表的长度:
/** 获得静态链表的长度 */ int GetStaticLinkList(StaticLinkList slList) { int count = 0; int cursor = slList[MAX_SIZE_SSL - 1].next; while (cursor) { //p = p->next cursor = slList[cursor].next; count++; } return count; }
静态链表的删除:
/** 删除链表中指定位置的元素 */ int DeleteStaticLinkList(StaticLinkList slList, int pos) { if (pos < 1 || pos > GetStaticLinkList(slList)) { return 0; } int cursor = MAX_SIZE_SSL - 1; //通过循环找到要删除位置的前缀结点 for (int i = 1; i <= pos - 1; i++) { cursor = slList[cursor].next; } int delIndex = slList[cursor].next; slList[cursor].next = slList[delIndex].next; //释放空间 FreeStaticLinkList(slList, delIndex); return 1; } /** 回收原始数组中指定下标的空间 */ void FreeStaticLinkList(StaticLinkList slList, int index) { //将下标为index的空闲结点回收到备用链表 slList[index].next = slList[0].next; //0号元素的next结点指向备用链表的第一个结点,表示index结点空闲 slList[0].next = index; }
四种链表的比较: