静态链表
静态链表,也是线性存储结构的一种,它兼顾了顺序表和链表的优点与一身
使用静态链表存储数据,数据全部存储在数组中,但存储位置是随机的,数据之间“一对一”的逻辑关系通过一个整形变量(称为“游标”,和指针的功能类似)维持
图中的链表在物理存储上是连续的,但是内部的顺序是随机的,由于大小的提前固定好的,随机的情况下,会有空的空间待存储数据,在静态数组中,需要用另外一个数组存储这些空闲的空间,这个数组就叫做备用链表
备用链表的作用是回收数组中未使用或之前使用过(目前为使用)的存储空间,留待后期使用
静态链表中设置备用链表的好处是,可以清楚地知道数组中是否有空闲位置,以便数据链表添加新数据时使用。
静态链表的创建
使用静态链表存储需要经过一下几个阶段:
- 在数据链表为初始化之前,数组中所有位置处于空闲状态,因此都应被连接在备用链表上
当静态链表中添加数据时,需提前从备用链表中摘取节点,以供新数据使用 - 备用链表摘除节点最简单的方法是摘除a[0]的直接后继节点;同样,向备用链表中添加空闲结点也是添加作为a[0]新的直接后继节点。因为a[0]是备用链表的第一个节点,我们知道他的位置,操作他的直接后继节点相对容易,无需遍历备用链表,耗费的时间复杂度为O(1)
- 在上面的基础上,在链表中添加节点的步骤就是每次添加时先找到备用链表的a[1],然后在这里添加元素
静态链表创建的全代码
#include<stdio.h>
#include<stdlib.h>
#define maxSize 6
typedef struct {
int data;
int cur;
}component;
void reserveArr(component *array);//将结构体数组中所有分量连接到备用链表中
int initArr(component *array);//初始化静态链表
void displayArr(component *array,int body);//输出函数
int mallocArr(component * array);//从备用链表上摘下空闲结点的函数
int main(){
component array[maxSize];
int body =initArr(array);
printf("静态链表为:\n");
displayArr(array,body);
return 0;
}
void reserveArr(component *array){
for(int i = 0;i < maxSize ; i++){
array[i].cur = i+1;//将每个数组分量链接到一起
array[i].data = -1;
}
array[maxSize-1].cur = 0;//链表最后一个结点的游标值为0
}
int mallocArr(component * array){
//若备用链表非空,则返回分配的节点下标,否则返回0(当分配最后一个结点时,该结点的游标值为0)
int i = array[0].cur;
if(array[0].cur){
array[0].cur = array[i].cur;
}
return i;
}
int initArr(component *array){
reserveArr(array);
int body = mallocArr(array);
int tempBody = body;
for(int i=1;i<4;i++){
int j = mallocArr(array);
array[tempBody].cur = j;
array[j].data = i;
tempBody = j;
}
array[tempBody].cur = 0;
return body;
}
void displayArr(component * array,int body){
int tempBody = body;
while(array[tempBody].cur){
printf("%d,%d ",array[tempBody].data,array[tempBody].cur);
tempBody = array[tempBody].cur;
}
printf("%d,%d\n",array[tempBody].data,array[tempBody].cur);
}
静态链表的基本操作
静态链表添加元素
实现步骤如下:
- 从备用链表中摘除一个结点,用于存储元素
- 找到表中要存储的位置的前一个结点,将该节点元素的游标赋值给新元素
- 将新元素所在数组中的下标赋值给前一个结点元素的游标
代码实现:
void insertArr(component *array,int add,int body,int a) {
int tempBody = body;
for(int i = 1; i < add ; i++){
tempBody = array[tempBody].cur;
}
int insert = mallocArr(array);
array[insert].data = a;
array[insert].cur = array[tempBody].cur;
array[tempBody].cur = insert;
}
静态链表删除元素
实现步骤如下:
- 将存有目标元素的节点从数据链表中摘除
- 将摘除节点添加到备用链表中,以便下次再用
代码实现:
void freeArr(component *array,int k){
array[k].cur = array[0].cur;
array[0].cur = k;
}
void deletArr(component *array,int body ,int a){
int tempBody = body;
while(array[tempBody].data!=a){
tempBody = array[tempBody].cur;
if(tempBody == 0){
printf("链表中没有此数据");
return;
}
}
int del = tempBody;
tempBody = body;//找到该节点的上一个节点,做删除操作
while (array[tempBody].cur != del){
tempBody = array[tempBody].cur;
}
array[tempBody].cur = array[del].cur;
freeArr(array,del);
}
查找元素
通过遍历整个链表来获取元素的位置
代码实现:
//在以body作为头结点的链表中查找数据域为elem的结点在数组中的位置
int selectElem(component * array,int body,char elem){
int tempBody=body;
//当游标值为0时,表示链表结束
while (array[tempBody].cur!=0) {
if (array[tempBody].data==elem) {
return tempBody;
}
tempBody=array[tempBody].cur;
}
return -1;//返回-1,表示在链表中没有找到该元素
}
更改数据
通过上面的查找元素,找到元素所在的节点,直接替换即可
//在以body作为头结点的链表中将数据域为oldElem的结点,数据域改为newElem
void amendElem(component * array,int body,char oldElem,char newElem){
int add=selectElem(array, body, oldElem);
if (add==-1) {
printf("无更改元素");
return;
}
array[add].data=newElem;
}
代码总结
#include<stdio.h>
#include<stdlib.h>
#define maxSize 7
typedef struct {
int data;//数据
int cur;//指针,指向下一个对应链表的空间
}component;
void reserveArr(component *array);//将结构体数组中所有分量连接到备用链表中
int initArr(component *array);//初始化静态链表
void displayArr(component *array,int body);//输出函数
int mallocArr(component * array);//从备用链表上摘下空闲结点的函数
void insertArr(component *array,int add,int body,int a);
void deletArr(component *array,int body ,int a);
void freeArr(component *array,int k);
int selectElem(component *array,int body,int a);
void amendElem(component *array,int body,int old,int newElem);
int main(){
component array[maxSize];
int body =initArr(array);
printf("静态链表为:\n");
displayArr(array,body);
printf("在链表的第2个位置后插入数字4:\n");
insertArr(array,3,body,4);
displayArr(array,body);
printf("删除上一步加入的4:\n");
deletArr(array,body,4);
displayArr(array,body);
printf("链表中3的位置在:%d \n",selectElem(array,body,3));
displayArr(array,body);
printf("将链表中的2替换成5:\n");
amendElem(array,body,2,5);
displayArr(array,body);
return 0;
}
void reserveArr(component *array){
for(int i = 0;i < maxSize ; i++){
array[i].cur = i+1;//将每个数组分量链接到一起
array[i].data = -1;
}
array[maxSize-1].cur = 0;//链表最后一个结点的游标值为0
}
int mallocArr(component * array){
//若备用链表非空,则返回分配的节点下标,否则返回0(当分配最后一个结点时,该结点的游标值为0)
int i = array[0].cur;
if(array[0].cur){
array[0].cur = array[i].cur;
}
return i;
}
int initArr(component *array){
reserveArr(array);
int body = mallocArr(array);
int tempBody = body;
for(int i=1;i<4;i++){
int j = mallocArr(array);
array[tempBody].cur = j;
array[j].data = i;
tempBody = j;
}
array[tempBody].cur = 0;
return body;
}
void displayArr(component * array,int body){
int tempBody = body;
while(array[tempBody].cur){
printf("%d,%d ",array[tempBody].data,array[tempBody].cur);
tempBody = array[tempBody].cur;
}
printf("%d,%d\n",array[tempBody].data,array[tempBody].cur);
}
void insertArr(component *array,int add,int body,int a) {
int tempBody = body;
for(int i = 1; i < add ; i++){
tempBody = array[tempBody].cur;
}
int insert = mallocArr(array);
array[insert].data = a;
array[insert].cur = array[tempBody].cur;
array[tempBody].cur = insert;
}
void freeArr(component *array,int k){
array[k].cur = array[0].cur;
array[0].cur = k;
}
void deletArr(component *array,int body ,int a){
int tempBody = body;
while(array[tempBody].data!=a){
tempBody = array[tempBody].cur;
if(tempBody == 0){
printf("链表中没有此数据");
return;
}
}
int del = tempBody;
tempBody = body;//找到该节点的上一个节点,做删除操作
while (array[tempBody].cur != del){
tempBody = array[tempBody].cur;
}
array[tempBody].cur = array[del].cur;
freeArr(array,del);
}
int selectElem(component *array,int body,int a){
int tempBody = body;
while(array[tempBody].cur != 0){
if(array[tempBody].data == a){
return tempBody;
}
tempBody = array[tempBody].cur;
}
return -1;//返回-1,表示在链表中没有找到该元素
}
void amendElem(component *array ,int body,int old,int newElem){
int add = selectElem(array,body,old);
if(add == -1){
printf("无更改元素\n");
return;
}
array[add].data = newElem;
}