C语言实现静态链表介绍

C语言实现静态链表介绍

静态链表其实是为了给没有指针的编程语言设计的一种实现单链表功能的方法。

3.1静态链表的优缺点

优点:

  • 在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序储存结构中的插入和删除操作需要移动大量元素的缺点。

缺点:

  • 没有解决连续存储分配(数组)带来的表长度难以确定的问题。
  • 失去了顺序储存结构随机存取的特性。
3.2实现原理

1、使用结构体数组,结构体有指针域 cur 和数据域 data

2、一个数组分量表示一个节点,用cur代替指针指示节点在数组中的相对位置

3、数组逻辑上分为两个链表:备用链表(空闲的节点)和数据链表(已被使用的节点)

3.4实现思路

在这里插入图片描述
插入操作思路:(例如要插入数据F到第3个位置)

(1)获取到数组第一个位置(即下标为0)的游标6,该游标指向备用链表(即为要插入的地方)更改下标0的游标为插入位置的游标(将0改为7,实现类似分配一个空间给数据链表,下标0的游标更改是让其指向新的备用链表的起始位置),将数据F写入数据域。
在这里插入图片描述
2)实现插入数据到第3个位置,则相当于将第2个位置的游标改为插入位置的下标,令其指向插入位置;再将插入位置的游标改为原第三个位置的下标,实现插入。
在这里插入图片描述
读取数据
在这里插入图片描述
删除数据原理大致一样。

/*
 * @Author: xgh
 * @Date: 2020-06-01 21:40:32
 * @LastEditTime: 2020-06-02 22:30:07
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \VS-CODE-C\.vscode\staticLinkedLists\staticLinkList.c
 */ 
#include "data.h"

Statue InitLink(StaticLinkList Space);
int GetLength(StaticLinkList Space);
void DisplayList(StaticLinkList Space);
Statue InsertList(StaticLinkList Space, int location, ElemType data);
Statue ListDelete(StaticLinkList Space, int location);
void Free_SLL(StaticLinkList Space, int index);

int main(void){

    int i, num = 5;

    StaticLinkList Space;
    InitLink(Space);

    for(i = 1; i <= 5; i++)
        InsertList(Space, i, i);
    
    DisplayList(Space);

    //在第3个位置插入数据7
    InsertList(Space, 3, 7);
    DisplayList(Space);

    //在第1个位置插入数据8
    InsertList(Space, 1, 8);
    DisplayList(Space);

    //在第8个位置插入数据9
    InsertList(Space, 8, 9);
    DisplayList(Space);

    // 删除第2个数据
    ListDelete(Space, 2);
    DisplayList(Space);

    printf("当前表长度为%d\n\n", GetLength(Space));


    return 0;
}

/**
 * @description: 初始化静态链表
 * @param {StaticLinkList Space: 静态链表存储结构数组} 
 * @return: 
 */
Statue InitLink(StaticLinkList Space){
    int i;
    
    // 遍历数组, 设置游标值
    for(i = 0; i < MAXSIZE - 1; i++){
        Space[i].cur = i + 1;  //0下标游标为1, 1下标游标为2, ...
    }

    Space[MAXSIZE].cur = 0;  //最后一个下标的游标为0

    printf("静态链表初始化成功\n\n");
    return SUCCESS;
}

/**
 * @description: 获取表有效数据个数长度, 返回静态链表中有效的数据个数
 * @param {StaticLinkList Space: 静态链表存储结构数组} 
 * @return: 表有效数据个数长度
 */
int GetLength(StaticLinkList Space)
{
    int len = 0;
    // 获取最后一个下标的游标, 因为最后一个下标的游标指向第一个数据的下标
    int index = Space[MAXSIZE - 1].cur;

    while(index){ // 判断是否有效
        len++;  // 长度加1
        index = Space[index].cur;
    }

    return len;
}

/**
 * @description: 获取静态链表数据
 * @param {StaticLinkList Space: 静态链表存储结构数组} 
 * @return: NULL
 */
void DisplayList(StaticLinkList Space){
    int index = Space[MAXSIZE - 1].cur;

    printf("表数据为:");
    while (index)
    {
        printf("%4d", Space[index].data);
        index = Space[index].cur;
    }

    printf("\n\n");   
}

/**
 * @description: 获取空闲分量的游标
 * @param {StaticLinkList Space: 静态链表存储结构数组} 
 * @return: 空闲分量的游标
 */
int malloc_SSL(StaticLinkList Space)
{
    int index = Space[0].cur;  // 获取数组第一个下标的游标, 因为这个游标指向空闲区域
    if(index){
        // 获取空闲分量的游标给到数组第0个下标的游标,指向新空闲区域
        // 把它的下一个分量用来做备份
        Space[0].cur = Space[index].cur;

        return index;
    }
    printf("空闲分量游标移动失败\n\n");
    return FAILURE;
}

/**
 * @description: 插入数据
 * @param {StaticLinkList Space: 静态链表存储结构数组}
 * @param {int location: 插入的位置 } 
 * @param {data: 插入的数据元素}
 * @return: ERROR: 插入位置错误
 * @return: FAILURE: 插入失败
 * @return: SUCCESS: 插入成功
 */
Statue InsertList(StaticLinkList Space, int location, ElemType data)
{
    int freeIndex, validIndex, i;
    
    // 判断插入位置的合法性
    if(location < 1 || location > GetLength(Space) + 1){
        printf("插入位置错误\n\n");
        return ERROER;
    }

    validIndex = MAXSIZE - 1; //数组最后一个位置的索引

    //获取空闲分量的索引(数组第0个索引的游标)
    freeIndex = malloc_SSL(Space);
    if(freeIndex){ // 表未满
        //将数据放入备用数组数据域(空闲分量)
        Space[freeIndex].data = data;
        // 前进至待插入的位置
        // 因为有效数据存放的索引是从1开始, 所以for循环从1开始比较方便
        for(i = 1; i <= location -1; i++){
            // validIndex是数组最后一个位置的下标, 游标指向第一个存放有效数据的
            // 元素下标, 以此类推。获取到第一个元素的下标后, for循环继续的话, 
            // 此时validIndex存放的是第一个元素的下标, 获取它的游标, 指向下一个
            // 元素, 直到循环结束, validIndex存放的是游标指向待插入位置的元素的索引
            validIndex = Space[validIndex].cur;
        }

        // 更改空闲向量的游标
        Space[freeIndex].cur = Space[validIndex].cur;
        // 更改指向插入数据的前一个数据的游标, 令其指向新数据
        Space[validIndex].cur = freeIndex;
        
        return SUCCESS;
    }  

    printf("插入失败\n\n");
    return FAILURE;
}

/**
 * @description: 删除数据
 * @param {StaticLinkList Space: 静态链表存储结构数组} 
 * @param {int location: 删除的位置}
 * @return: ERROR: 删除位置错误
 * @return: SUCCESS: 删除成功
 */
Statue ListDelete(StaticLinkList Space, int location)
{
    int freeIndex, validIndex, i;
    
    // 判断插入位置的合法性
    if(location < 1 || location > GetLength(Space) + 1){
        printf("删除位置错误\n\n");
        return ERROER;
    }

    validIndex = MAXSIZE - 1; //数组最后一个位置的索引
    
    // 获取待删除位置的前一个数据索引
    for(i = 1; i <= location; i++){
        validIndex = Space[validIndex].cur;
    }

    freeIndex = Space[validIndex].cur;  // 获取到待删除数据的索引
    //将待删除数据的游标给上一个元素的游标, 让其可以指向待删除数据的后一个数据元素
    Space[validIndex].cur = Space[freeIndex].cur;  

    Free_SLL(Space, freeIndex);

    return SUCCESS;

}

/**
 * @description: 将下标为index的空闲结点回收到备用数组
 * @param {StaticLinkList Space: 静态链表存储结构数组}
 * @param {int index: 删除的位置} 
 * @return: NULL
 */
void Free_SLL(StaticLinkList Space, int index)
{
    // 将删除的数据的游标改为第0个索引的游标, 即原指向空闲向量的游标
    Space[index].cur = Space[0].cur;

    // 将第0个索引的游标的指向更改为删除数据的索引, 实现回收
    Space[0].cur = index;
}

data.h

/*
 * @Author: xgh
 * @Date: 2020-06-01 21:41:18
 * @LastEditTime: 2020-06-03 22:12:37
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \VS-CODE-C\.vscode\staticLinkedLists\data.h
 */ 
#ifndef __DATA_H__
#define __DATA_H__

#include <stdio.h>
#include <stdlib.h>

#define SUCCESS 1  //成功
#define FAILURE 0  //失败
#define ERROER 0 //错误

typedef int Statue;  // 为int取别名,用于区分表示执行状态的int
typedef int ElemType;  // 数据域类型

#define MAXSIZE 30  // 静态链表长 

// 定义静态链表结构体
typedef struct{
    ElemType data;  // 数据
    int cur;  // 游标
}component, StaticLinkList[MAXSIZE];

#endif

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值