静态链表

什么是静态链表

  • 在某些高级语言中,没有指针类型,所以想使用链表,得靠其它手段,比如静态链表
  • 静态链表是顺序表和链表的结合,在初始化时申请一定大小的空间(可以等同于定义一定长度的数组),数组的元素是一个结构体变量,结构体内有两个元素,一是数据,二是游标(相当于链表中的指针),游标保存的是下一个节点的下标
  • 静态链表内部有两个链表,数据链表和备用链表
  • 数据链表和备用链表各有一个头节点(链表没有头节点操作非常不方便),因此如果申请10个节点的空间,能保存数据的仅有8个节点
  • 一般情况下,第一个节点,也就是下标为0的元素,作为备用节点的头节点,最后一个元素,也就是最大下标的元素,作为数据链表的头节点
  • 初始化后的静态链表如下所示:
typedef struct linknode
{
    int data;               //数据
    int cursor;             //游标,指向下一个节点
}node;

//初始化长度为10的静态链表
--------- Spare list ---------
list[0] : data = 0, cursor = 1
list[1] : data = 0, cursor = 2
list[2] : data = 0, cursor = 3
list[3] : data = 0, cursor = 4
list[4] : data = 0, cursor = 5
list[5] : data = 0, cursor = 6
list[6] : data = 0, cursor = 7
list[7] : data = 0, cursor = 8
list[8] : data = 0, cursor = 0
--------- data list ---------
list[9] : data = 0, cursor = 0

静态链表在增删改查时,也要顾及到内部的两个链表,比如增加数据时,从备用链表取出一个节点,放入数据,再将该节点加入数据链表,以下是代码部分

main.cpp

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

using namespace std;
#define size 10         //总节点数

int main(int argc, char *argv[])
{
    node *list = NULL;
    list = list_init(size);
    if(list == NULL)
        return 0;
    list_display(list);
    cout << endl;

    for (int i = 0; i < 12; i++)
    {
        list_add_tail(list, i+5);
    }
    list_display(list);

    list_del(list, 5);
    list_del(list, 10);
    list_display(list);

    list_find_data(list, 8);

    list = list_deinit(list);

    return 0;
}

linklist.cpp

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include "linklist.h"

using namespace std;
int listsize = 0;                               //总节点数

//初始化静态链表
node * list_init(int size)
{
    int i = 0;
    node *pnode = (node *)malloc(sizeof(node) * size);
    if(pnode == NULL)
    {
        cout << "malloc err" << endl;
        return NULL;
    }
    listsize = size;                            //记录总节点数,方便判满判空时使用
    memset(pnode, 0, sizeof(node) * size);      //所有元素初始化为0
    for (i = 0; i < size; i++)
    {
        pnode[i].cursor = i+1;                  //初始化备用链表的游标
    }
    pnode[i-1].cursor = 0;                      //数据链表头节点,游标置为0
    pnode[i-2].cursor = 0;                      //备用链表最后一个节点,游标置为0
    return pnode;
}

//释放申请的内存
node * list_deinit(node *pnode)
{
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return NULL;    
    }
    free(pnode);
    return NULL;
}

//在数据链表的头部插入
int list_add_head(node *pnode, int data)
{
    //链表不存在
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
     //数据链表已满(备用链表已空)
    if(pnode[0].cursor == 0)    //备用链表头节点指向自己
    {
        cout << "data list is full" << endl;
        return -1;    
    }
    //从备用链表中取出一个节点
    int index = pnode[0].cursor;            //这是从备用链表取出的节点,用来存放数据
    pnode[0].cursor = pnode[index].cursor;  //让备用链表的头节点,指向取出节点的下一个节点
    pnode[index].data = data;               //保存数据
    //将取出的节点放入数据链表
    pnode[index].cursor = pnode[listsize - 1].cursor;   //取出的节点游标指向数据链表的首元节点
    pnode[listsize - 1].cursor = index;     //数据链表的头节点指向取出的节点
    return 0;
}

//在数据链表的尾部插入
int list_add_tail(node *pnode, int data)
{
    //链表不存在
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
    //数据链表已满(备用链表已空)
    if(pnode[0].cursor == 0)    //备用链表头节点指向自己
    {
        cout << "data list is full" << endl;
        return -1;    
    }
    //从备用链表中取出一个节点
    int index = pnode[0].cursor;            //这是从备用链表取出的节点,用来存放数据
    pnode[0].cursor = pnode[index].cursor;  //让备用链表的头节点,指向取出节点的下一个节点
    pnode[index].data = data;               //保存数据
    //找到数据链表的尾部节点
    int idata = listsize - 1;               //先定位到数据链表的头节点
    while(pnode[idata].cursor != 0)
    {
        idata = pnode[idata].cursor;
    }
    //将取出的节点放入数据链表
    pnode[index].cursor = pnode[idata].cursor;  //取出的节点游标指向0(类似于普通链表的末尾指向NULL)
    pnode[idata].cursor = index;                //原数据链表尾节点指向取出的节点
    return 0;
}

//删除指定元素
//暂不考虑两个节点数据相同的情况
int list_del(node *pnode, int data)
{
    int idata = listsize - 1;       //数据链表的头节点位置
    int idatalast;
    //链表不存在
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
    //数据链表为空
    if(pnode[idata].cursor == 0)    //备用链表头节点指向自己
    {
        cout << "data list is empty" << endl;
        return -1;    
    }
    //寻找数据元素
    while(pnode[idata].cursor != 0)
    {
        idatalast = idata;
        idata = pnode[idata].cursor;
        if(pnode[idata].data == data)   //找到了,此时idata为要删除节点的下标,idatalast为要删除节点的上一个节点下标
        {
            //将该节点从数据节点从删除
            pnode[idatalast].cursor = pnode[idata].cursor;
            pnode[idata].data = 0;
            //将该节点加入备用链表
            pnode[idata].cursor = pnode[0].cursor;
            pnode[0].cursor = idata;
            return 0;
        }
    }
    return -1;
}

//改变指定元素
//暂不考虑两个节点数据相同的情况
int list_change(node *pnode, int olddata, int newdata)
{
    int idata = listsize - 1;       //数据链表的头节点位置
    int idatalast;
    //链表不存在
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
    //数据链表为空
    if(pnode[idata].cursor == 0)    //备用链表头节点指向自己
    {
        cout << "data list is empty" << endl;
        return -1;    
    }
    //寻找数据元素
    while(pnode[idata].cursor != 0)
    {
        idatalast = idata;
        idata = pnode[idata].cursor;
        if(pnode[idata].data == olddata)   //找到了
        {
            pnode[idata].data = newdata;
            return 0;
        }
    }
    return -1;
}

//查找指定数据的元素
//暂不考虑两个节点数据相同的情况
int list_find_data(node *pnode, int data)
{
    int idata = listsize - 1;       //数据链表的头节点位置
    int idatalast;
    //链表不存在
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
    //数据链表为空
    if(pnode[idata].cursor == 0)    //备用链表头节点指向自己
    {
        cout << "data list is empty" << endl;
        return -1;    
    }
    //寻找数据元素
    while(pnode[idata].cursor != 0)
    {
        idatalast = idata;
        idata = pnode[idata].cursor;
        if(pnode[idata].data == data)   //找到了
        {
            cout << "finded! list[" << idata << "] = "<< data << endl;
            return 0;
        }
    }
    return -1;
}

//显示静态链表所有元素
int list_display(node *pnode)
{
    int i = 0;
    if(pnode == NULL)
    {
        cout << "list pointer is NULL" << endl;
        return -1;    
    }
    //显示备用链表
    //如果备用链表为空,则首次while判断时,头节点游标指向本身,不满足循环条件,直接退出
    cout << "--------- Spare list ---------" << endl;
    while(pnode[i].cursor != 0)
    {
        cout << "list[" << i << "] : data = " << pnode[i].data;
        cout << ", cursor = " << pnode[i].cursor << endl;
        i = pnode[i].cursor;
    }
    //显示备用链表的最后一个节点,该节点游标指向头节点,不满足循环条件,因此单独打印
    cout << "list[" << i << "] : data = " << pnode[i].data;
    cout << ", cursor = " << pnode[i].cursor << endl;

    //显示数据链表
    //数据链表的头节点为整个链表末尾的那个节点,该节点不用于存储数据
    //如果数据链表为空,则数据链表头节点游标指向0,即指向了备用链表头节点
    cout << "--------- data list ---------" << endl;
    i = listsize - 1;
    while(pnode[i].cursor != 0)
    {
        cout << "list[" << i << "] : data = " << pnode[i].data;
        cout << ", cursor = " << pnode[i].cursor << endl;
        i = pnode[i].cursor;
    }
    //显示数据链表的最后一个节点,该节点游标指向备用链表头节点,不满足循环条件,因此单独打印
    cout << "list[" << i << "] : data = " << pnode[i].data;
    cout << ", cursor = " << pnode[i].cursor << endl;
    return 0;
}

linklist.h

#ifndef LINKLIST_H
#define LINKLIST_H

//静态链表
//静态链表有两个特殊的节点不存放数据
//第一个节点,游标指向备用链表,相当于备用链表的头节点
//最后一个节点,游标指向数据链表,相当于数据链表的头节点
typedef struct linknode
{
    int data;               //数据
    int cursor;             //游标,指向下一个节点
}node;

node * list_init(int size);
node *list_deinit(node *pnode);
int list_add_head(node *pnode, int data);
int list_add_tail(node *pnode, int data);
int list_del(node *pnode, int data);
int list_change(node *pnode, int olddata, int newdata);
int list_find_data(node *pnode, int data);
int list_display(node *pnode);

#endif
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
静态链表是一种使用数组实现的链结构,它通过数组中的元素来模拟链中的节点,并使用一个特殊的指针(游标)来示节点之间的逻辑关系。静态链表的优点是实现简单,不需要频繁地申请和释放内存空间,但缺点是插入和删除操作比较麻烦,需要手动维护游标指针。 以下是一个简单的Python静态链表的实现示例[^1]: ```python class StaticLinkedList: def __init__(self, size): self.data = [None] * size # 存储数据的数组 self.next = [i + 1 for i in range(size)] # 游标数组,用于维护节点之间的逻辑关系 self.next[-1] = -1 # 最后一个元素的游标为-1,示链的末尾 self.head = -1 # 头指针,指向链的第一个节点 def is_empty(self): return self.head == -1 def is_full(self): return self.next == -1 def insert(self, value): if self.is_full(): print("StaticLinkedList is full") return new_node = self.next # 获取一个空闲节点 self.next = self.next[new_node] # 更新空闲节点的游标 self.data[new_node] = value # 在空闲节点中存储数据 if self.is_empty(): self.head = new_node self.next[new_node] = -1 else: current = self.head while self.next[current] != -1: current = self.next[current] self.next[current] = new_node self.next[new_node] = -1 def delete(self, value): if self.is_empty(): print("StaticLinkedList is empty") return prev = -1 current = self.head while current != -1: if self.data[current] == value: break prev = current current = self.next[current] if current == -1: print("Value not found") return if prev == -1: self.head = self.next[current] else: self.next[prev] = self.next[current] self.next[current] = self.next # 将删除的节点加入空闲节点链 self.next = current def display(self): if self.is_empty(): print("StaticLinkedList is empty") return current = self.head while current != -1: print(self.data[current], end=" ") current = self.next[current] print() # 创建一个容量为5的静态链表 static_list = StaticLinkedList(5) # 插入数据 static_list.insert(1) static_list.insert(2) static_list.insert(3) # 删除数据 static_list.delete(2) # 显示链中的数据 static_list.display() ``` 输出结果为: ``` 1 3 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值