2-3 线性表之静态链表 及3其 C++实现

 更多系列博文请点击:0-数据结构与算法链接目录 

2-3 线性表之静态链表

1、基本定义

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

静态链表,仍需要预先分配一个较大的空间,但是在作为线性表的插入和删除操作时不需要移动元素,仅仅需修改指针,故仍具有链式存储结构的主要优点。

静态链表使用数组来存储数据(和顺序表一样),但是存储位置是随机的,数据之间“一对一的逻辑关系通过一个“游标”来实现(和链表又类似)。

所以静态链表需要2部分的信息,

①数据域,用于存储数据元素;

②游标:其实就是数组的下标,来表示直接后继元素在数组中的位置;

 

C语言实现静态链表结构体定义:

#define Max 100

typedef struct {

int data; //数据域

int cur; //游标

} static_link_list[Max];

 

但其实静态链表中,除了数据本身通过游标组成的链表外,还需要一条连接各个空位置的链表,称为备用链表

备用链表的作用是存放目前未使用的空间,留作后用

所以其实静态链表使用数组申请的物理空间中,存在两个链表,一个连接数据,一个连接空位置。

静态链表中设置备用链表的好处是,可以知道我们是否还有空位置可以存储数据。

 

习惯上来说,备用链表的头结点为数组的首元素arr[0], 而数据链表的头结点为数组的最后一个元素arr[Max-1]

这个记住就行,不用去想为什么。

后面我们就把数据链表简称为链表或者静态链表。

其实静态链表完全可以视为用顺序表的方式实现 带头结点的单链表,程序之中有很多相似的地方,只是变量换了个名称而已。

 

2、部分程序讲解

初始化静态链表

令最后一个元素(链表头结点)的游标为0,表示指向备用链表的头结点,表示该链表为空

void InitList(static_link_list L)

{

L[MAX-1].cur = 0; //令链表头结点为空

for (int i=0; i<MAX-2; i++) //其余元素构成备用链表,即每个结点的游标都指向其下一个位置

L[i].cur = i+1;

L[MAX-2].cur = 0; //备用链表最后一个元素置为空

}

//链表头结点为空很好理解,因为游标是指向 直接后继元素的 位置,而空链表没有元素,所以头结点游标为0,表示直接后继就是备用链表的头结点,表示没有数据元素。而备用链表的最后一个结点 L[MAX-2]为什么游标也为0呢? 这是因为这已经是备用链表的最后一个元素了,它后面没有后继了!所以可以理解为单链表的最后一个结点的next为null,道理是一样的

 

②从备用空间中分配结点出来使用:

int mallocArr(static_link_list L){

int i = L[0].cur; //从备用链表中的头结点L[0]取出其游标,表示下一个可用的结点的位置

if (i) { /*如果这个位置不为0,说明还有空间可用,这就是为什么我们要把备用结点的最后一个元素L[Max-2]的游标设为0,表示后面没有可取的位置!*/

L[0].cur = L[i].cur; //把头结点的下一个位置,指向L[i]的下一个位置,使得L[i]断开

//为什么不给L[i].cur指定值呢???因为取出来之后,执行插入到数据链表中的时候,会有这一步

}

return i; //返回我们取出的i位置

}

③从数据链表中释放结点到备用空间

void Free_node(static_link_list L){

/*相当于链表中的在L[0]后面插入L[k]*/

L[k].cur = L[0].cur;// 将L[k]的游标指向L[0]的游标指向的位置

L[0].cur = k;//将L[0]的游标指向k

为什么我要单独讲一下这三个程序呢,因为我说过可以把静态链表当作带头结点的单链表来理解,

但是对于动态链表,是采用 malloc或new来从动态存储区分配空间,采用free或者delete来释放;而静态链表可用的区域,

是我们的备用链表里的区域,所以就要自己写两个函数来模拟 上述开辟和释放内存的行为。

然后就是静态链表尾部 不同于 单链表尾部指向null, 而是游标指向0,即备用链表头结点。

其余的操作都跟有头结点的单向链表几乎一致,就是next指针换成了 cur 游标而已,而且由于不是动态分配的内存,最后不用写Destory函数来手动销毁链表

3.头文件 

static_link_list.h

#ifndef STATIC_LINK_LIST_H_
#define STATIC_LINK_LIST_H_
#define MAX 10
typedef struct {
	int data;
	int cur;
} s_link_list[MAX];

void InitList(s_link_list L);
int mallocArr(s_link_list L);
void Free_node(s_link_list L, int k);

void CreateList(s_link_list L);
int LenList(s_link_list L);
void ShowList(s_link_list L);

void ListInsert(s_link_list L, int i, int x);
void DeleteList(s_link_list L, int i);
#endif // !STATIC_LINK_LIST_H_

4.函数定义文件

static_link_list.cpp

#include<iostream>
#include"static_link_list.h"
using std::cin;
using std::cout;
using std::endl;

void InitList(s_link_list L) {
	L[MAX - 1].cur = 0;

	for (int i = 0; i < MAX - 2; i++)
		L[i].cur = i + 1;

	L[MAX - 2].cur = 0;
}

int mallocArr(s_link_list L) {
	
	int i = L[0].cur;
	if (i == 0) {
		cout << "\n已经没有剩余空间可用了!最多只能有 "<<MAX-2<<" 个数据元素!" << endl;
		return 0;
	}
	else{
		L[0].cur = L[i].cur;
		//L[i].cur = 0;
		return i;
	}
}

void Free_node(s_link_list L, int k) {

	/*相当于链表中的在L[0]后面插入L[k]*/
	L[k].cur = L[0].cur;// 将L[k]的游标指向L[0]的游标指向的位置
	L[0].cur = k;//将L[0]的游标指向k

}

void CreateList(s_link_list L) {
	int x = 0;
	int j = 1;

	/*初始化静态链表*/
	InitList(L);

	/*k指向头结点的位置*/
	int k = MAX-1;

	while (cin >> x) {
		/*采用尾插法,每次都先创建尾巴结点*/
		int s = mallocArr(L);
		if (s == 0)
			return;
		L[s].data = x;
		L[s].cur = 0;

		while (L[k].cur)
			k = L[k].cur;
		L[k].cur = s;
		
	}

	cin.clear();
	while(cin.get() != '\n')
		continue;
}

int LenList(s_link_list L) {
	/*指向头结点位置*/
	int k = MAX - 1;
	int j = 0;
	while (L[k].cur) {
		j++;
		k = L[k].cur;
	}
	return j;
}

void ShowList(s_link_list L) {
	/*判断是否为空*/
	if (L[MAX - 1].cur == 0) {
		cout << "\n静态链表为空!!" << endl;
		return;
	}
	/*k指向头结点*/
	int k = MAX - 1;
	int j = 0;
	cout << "\n链表内容为: " << endl;
	while (L[k].cur) {
		j++;
		k = L[k].cur;
		cout << "L[" << j << "]=" << L[k].data << "   ";
	}
	cout << endl;
}

void ListInsert(s_link_list L, int i, int x) {
	int k = MAX - 1;
	int j = 0;
	while (L[k].cur && j<i-1) {
		j++;
		k=L[k].cur;
	}
	if (j != i - 1) {
		cout << "\n插入的位置 ["<<i<<"] 不合理!不执行 插入操作!" << endl;
		return;
	}
	int s = mallocArr(L);
	if (s == 0) {
		cout << "\n无剩余空间,不执行插入操作!" << endl;
		return;
	}
	L[s].data = x;
	L[s].cur = L[k].cur;
	L[k].cur = s;
}

void DeleteList(s_link_list L, int i){
	if (L[MAX - 1].cur == 0) {
		cout << "\n链表为空!不执行删除操作!!" << endl;
		return;
	}

	int k = MAX - 1;
	int j = 0;
	while (L[k].cur&&j < i - 1) {
		j++;
		k = L[k].cur;
	}
	if (j != i - 1 && L[k].cur == 0) {
		cout << "\n想要删除的位置 [" << i << "] 不合理! 不执行删除操作!!" << endl;
	}

	int s = L[k].cur;
	L[k].cur = L[s].cur;
	Free_node(L,s);
}

5.主函数文件

use_static_linklist.cpp

#include<iostream>
#include"static_link_list.h"

using std::cout;
using std::cin;
using std::endl;

int main() {

	s_link_list L;
	cout << "请依次输入数据创建静态链表, 以 q 为终止信号!" << endl;
	CreateList(L);
	cout << "\n该静态链表的长度为:" << LenList(L) << endl;
	ShowList(L);
	ListInsert(L,3,333); ShowList(L);

	cout << "\n删除第4个元素:" << endl;
	DeleteList(L, 4); ShowList(L);
	getchar();
	return 0;
}

若有错误 请不吝指出 谢谢

 更多系列博文请点击:0-数据结构与算法链接目录 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值