数据结构个人笔记 第六课 静态链表

静态链表

静态链表,也是线性存储结构的一种,它兼顾了顺序表和链表的优点与一身

使用静态链表存储数据,数据全部存储在数组中,但存储位置是随机的,数据之间“一对一”的逻辑关系通过一个整形变量(称为“游标”,和指针的功能类似)维持

静态链表
图中的链表在物理存储上是连续的,但是内部的顺序是随机的,由于大小的提前固定好的,随机的情况下,会有空的空间待存储数据,在静态数组中,需要用另外一个数组存储这些空闲的空间,这个数组就叫做备用链表

备用链表的作用是回收数组中未使用或之前使用过(目前为使用)的存储空间,留待后期使用

静态链表中设置备用链表的好处是,可以清楚地知道数组中是否有空闲位置,以便数据链表添加新数据时使用。

静态链表的创建

使用静态链表存储需要经过一下几个阶段:

  1. 在数据链表为初始化之前,数组中所有位置处于空闲状态,因此都应被连接在备用链表上
    当静态链表中添加数据时,需提前从备用链表中摘取节点,以供新数据使用
  2. 备用链表摘除节点最简单的方法是摘除a[0]的直接后继节点;同样,向备用链表中添加空闲结点也是添加作为a[0]新的直接后继节点。因为a[0]是备用链表的第一个节点,我们知道他的位置,操作他的直接后继节点相对容易,无需遍历备用链表,耗费的时间复杂度为O(1)
  3. 在上面的基础上,在链表中添加节点的步骤就是每次添加时先找到备用链表的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);
}

静态链表的基本操作

静态链表添加元素

实现步骤如下:

  1. 从备用链表中摘除一个结点,用于存储元素
  2. 找到表中要存储的位置的前一个结点,将该节点元素的游标赋值给新元素
  3. 将新元素所在数组中的下标赋值给前一个结点元素的游标

代码实现:

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;
}

静态链表删除元素

实现步骤如下:

  1. 将存有目标元素的节点从数据链表中摘除
  2. 将摘除节点添加到备用链表中,以便下次再用

代码实现:

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值