C语言链式存储之静态链表

本文深入讲解静态链表的实现原理及关键操作,包括初始化、添加、插入、删除元素等核心功能,并提供完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.什么是静态链表

2.添加一个新元素

3.插入结点

4.删除结点

5.静态链表的初始化

6.打印静态链表

7. 查找给定结点的上一个结点的下标

8.主函数


1.什么是静态链表

   用数组来代替指针,描述单链表。定义一个结构体,结构体中包含两个整形变量,第一个整形变量等价于链表中的data域,第二个整形元素等价于单链表中的next指针域,这个变量用cur表示,用来存储下一个元素的数组下标。结构体类型如下:

struct node{
	int data;       //数据域
	int cur;        //指针域
}slist[M],snode; 

注意:<1>静态链表中对数组中的第一个元素和最后一个元素做特殊处理,第一个元素相当于单链表中的尾指针,数据域不存数据,cur域用来存储备用链表中的第一个元素的下标;最后一个元素中的data域同样不存数据,cur域用来存储第一个放数据的元素的下标,该结点相当于单链表中的头结点(注意不是首结点);

           <2>备用链表:未被使用的数组元素被称为备用链表;

2.添加一个新元素

node* createnode(node* p,int e)
{
	int a,l;
	l = 0;
	if(p[M-1].cur==0)        //表示当前链表为空
	{
	   a = 1;
	   p[a].data = e;        //将数据放到下标为1的结点中
	   p[0].cur =  p[a].cur; //改变第一个结点中所存储的备用链表的第一个节点的下标 
	   p[a].cur = 0;         //将尾结点指向空 
	   p[M-1].cur = 1;       //将头结点中的下标指向首结点 
	} 
	else
	{
		a = p[0].cur;         //找到备用链表中第一个结点的下标 
		p[0].cur = p[a].cur;  //备用链表中的下一个元素的下标 
		l = findcur(p,0);     //找到链表中cur域为0的结点的下标 
		p[l].cur = a;         //将之前的尾结点指向新插入的结点(即将之前尾结点的cur域赋值为新结点的下标值) 
		p[a].data = e;        //完成对新结点数据域的赋值 
		p[a].cur  = 0;	      //使其指向空 
	}
	return p;
}

3.插入结点​​​​​​​

  (这里和书上实现不太一样)

要点:<1>首先获取备用链表中的第一个空闲结点,作为这个插入元素的存储结点,将数据存到这个节点的数据域中;

           <2>获取第i个元素之前的结点的下标,让这个结点指向插入结点(即将插入结点的下标赋值给i之前结点的cur域);

           <3>将这个新插入结点的cur赋值为i元素的下标,即完成新插入结点的指向。

//在第i个元素之前插入元素e
node* insertnode(node* p,int i,int e)
{
	int l,j;
	//如果当前表是空的直接退出 
    if(p[M-1].cur==0)
	{
		printf("链表为空,不能插入!\n");
		return p; 
	} 
	if(i<1||i>(M-1))
	{
		printf("要插入的结点不在链表范围内,不能插入\n");
		return p;
	}
	l = p[0].cur;             //先找到备用链表中第一个空闲结点
	if(l)                     //表示链表没有满,可以取到空闲结点 
	{
		p[0].cur = p[l].cur;  //将备用链表的首结点 放在第一个链表的cur中 
		j = findcur(p,i);     //找到下标为i的那个结点的前一个节点的下标 
		p[j].cur = l;         //将前一个结点指向这个新结点   
		p[l].data = e;
		p[l].cur = i;		  //插入的这个结点指向i结点1 
	}
	return p;
}

 

4.删除结点

要点:<1>查找要删除结点的上一个结点,使该结点的游标(cur)指向要删除结点的下一个结点

           <2>回收删除的结点,将该回收结点放到备用链表头:第一,将第一个结点的游标赋值给回收结点的游标;第二,将第一                  个结点的游标指向回收结点。

//删除链表中第l个结点
node* deletenode(node* p,int l)
{
	if(p[M-1].cur == 0)        //头指针指向空,则链表为空不能删除 
	{
		printf("the list is null\n");
		return p;
	}
	if((l<1)||(l>=(M-2)))          //如果输入的位置在第一个和最后一个结点之外,也不能删除,输入范围不对 
	{
		printf("the location is error!\n");
		return p;
	}
	int temp;
	int c;
	c = findcur(p,l);         //找到上一个指向要输入的这个结点的下标 
	p[c].cur = p[l].cur;      //将要删除结点的上一个结点的cur指向要删除结点的下一个结点 
   	p[l].cur=p[0].cur ;       //将删除了的这个空闲结点的游标指向0中存的游标 ,实现将该结点会收到备用链表中 
	p[0].cur = l;            //将0中存的第一个备用链表的游标指向刚刚删除的这个结点 
	return p;	
} 

 

5.静态链表的初始化

目标:将链表初始化为备用链表

要点:1. 从第一个结点开始,使其cur指向下一个结点(即备用链表的首结点为1,后面的结点依次连接起来);

           2. 最后一个元素的cur域置为0,表示该链表为空链表;

//初始化所要做的操作就是将所有的cur都置为下一个元素的数组下标,尤其是最后一个元素的下标置为0,表示该链表为空
node* initlist(node* p)
{
	int i;
	for(i=0;i<M-1;i++)
	{
		p[i].cur =(i+1);
	}
	p[M-1].cur = 0;                       //表示当前链表为空
	return p; 
} 

6.打印静态链表

int plist(node* p)
{
	int m = p[M-1].cur;               //从首结点开始打印
	while(m!=0)
	{
		printf("%d,%d\n",m,p[m].data);
		m = p[m].cur;
	}
	return 0;
}

7. 查找给定结点的上一个结点的下标

int findcur(node* p,int c)
{
	int i=1;
	int l=(M-1);
	while(c==0)
	{
		if(p[i].cur == 0)
		{
			return i;
		}
		else
		{
			i = p[i].cur;
		}
	}
	for(i=1;i<c;i++)    //找到i元素的上一个结点的下标 
	{
         l=p[l].cur;
	}
	return l;
}

8.主函数

#include "stdio.h"
#include "stdlib.h"
#define M 1000 
struct node{
	int data;
	int cur;
}slist[M],snode; 
int main()
{
	node *p;
	int n,i=0,e;	
	p = &slist[0];
	p = initlist(p);
	scanf("%d",&n);
	while(n!=i)
	{
		scanf("%d",&e);
		createnode(p,e);
		i++;
	}
	p = insertnode(p,2,13);
	plist(p);
	p = deletenode(p,5);
	plist(p);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值