Sequential storage and implementation of linear tables


directory

1. What is the sequential storage of linear tables

1. Definition of sequential storage structure of linear table

1. Static allocation

2. Dynamic allocation

2. Basic operation

1. Initialization of the linear table

1. Static sequence table:

2. Dynamic sequence table

2. Insert operation

1. Static sequence table

2. Dynamic sequence table

3. Delete operation

1. Static sequence table:

2. Dynamic sequence table:

4. Complete code

1. Dynamic sequence table

2. Static sequence table

V. Summary

1. What is the sequential storage of linear tables

The sequential storage of the linear table refers to using a group of storage units with continuous addresses in the computer to sequentially store the data elements of the linear table.

The sequential storage structure of the linear table is a random storage structure.

​​​​​​​


1. Definition of sequential storage structure of linear table

        There are two ways to define the sequential storage structure of the linear table, one is static allocation and the other is dynamic allocation.

1. Static allocation

        When we do not consider the change of the table length of the linear table, we can use the static allocation method;

        In C language, arrays also have the characteristics of random access, so we use arrays to describe sequential storage structures in data structures. Therefore, the static allocation method of the sequence table is defined as follows:

        Where maxSize represents the maximum number of data elements in the linear table

        length represents the maximum value of the data element.

#define maxSize 100  //顺序表中的数据元素的最大个数

typedef struct SeqList{
    int data[maxSize] ;//值域
    int length;
}SeqList;

2. Dynamic allocation

Since the length of the linear table is variable, and the maximum storage space required varies with the access problem, we can use the following code to define the sequential storage structure of the linear table.

#define LIST_INIT_SIZE 100  //线性表存储空间的初始分配量
#define LISTINCREMENT 10    //线性表存储空间的初始分配增量
typedef struct {
    int *elem;   // 存储空间基地址 指示动态分配数组的指针,也就是malloc函数返回的分配空间的起始地址
    int length;  // 当前长度
    int maxSize; // 当前分配的额存储容量

}SeqList;


2. Basic operation




1. Initialization of the linear table

1. Static sequence table:

We only need to set the length of the sequence table to 0


SeqList initSeqList(void){
    SeqList seqList ;
    seqList.length = 0;
    return  seqList;
}

2. Dynamic sequence table

We can initialize the dynamic sequence table as follows:

1. Construct an empty table and allocate storage space. If the allocation fails, exit the program.

2. Set the length of the linear table to 0.

3. Set the initial allocation space capacity of the linear table.

code show as below:

//#pragma mark -- 初始化线性表(构造一个空表)
SeqList initSeqList(void){
    SeqList seqList;
    seqList.elem = (int *)malloc(list_init_size * sizeof(int));//构造空表
    if (!seqList.elem) {
        printf("==========>>>>>初始化失败,程序退出<<<<<==========\n");
        exit(0);
    }else{
        printf("==========>>>>>线性表初始化成功<<<<<==========\n");
    }
    seqList.length = 0;
    seqList.listSize = list_init_size;
    return seqList;
}

2. Insert operation

To insert a linear table, we need to know two elements:

1. We need to know the insertion position of the linear table,

2. We need to know the value to insert.

1. Static sequence table


/// 顺序表的插入操作
/// @param location 插入位置
/// @param value 插入的值
SeqList seqList_insert(SeqList seqList,int location,int value){
    if (location <1 || location > seqList.length + 1) {
        printf("插入位置非法,程序结束\n");
        return  seqList;
    }
    for (int i = seqList.length -1; i >= location - 1 ; i--) {
        seqList.data[i+1] = seqList.data[i];
    }
    seqList.data[location - 1] = value;
    seqList.length ++;
    return  seqList;
}

2. Dynamic sequence table

During the insertion process, we need to consider the legality of the insertion location and whether the storage space of the current program is full.

The main code is as follows:

//#pragma mark -- 插入操作

/// 线性表的插入操作
/// @param seqList 要插入的线性表
/// @param location 插入位置
/// @param value 要插入的值
SeqList seqList_insert(SeqList seqList,int location,int value){
    if (location <1 || location>seqList.length+1) {
        printf("插入失败,程序退出");
        exit(0);
    }
    if (seqList.length > seqList.listSize) {//当前存储空间已满 重新分配存储空间
        int * newbase = (int *)malloc(sizeof(int)*(seqList.length + list_initCrement));
        if (!newbase) {
            printf("存储空间分失败,程序退出");
            exit(0);
        }
        seqList.elem = newbase;
        seqList.listSize += list_initCrement;
    }
    for (int i = seqList.length - 1; i >= location - 1 ; i--) {
        seqList.elem[i+1] = seqList.elem[i];
    }
    seqList.elem[location-1] = value;
    seqList.length++;
    return  seqList;
}


3. Delete operation

When we perform a delete operation on a linear table, we need to know the subscript of the data element to be deleted. When performing a delete operation, the data after the insertion position needs to move forward sequentially. After the deletion is complete, remember to update the table length of the linear table. The main code is as follows:

1. Static sequence table:

/// 顺序表的删除操作
/// @param seqList 要操作的顺序表
/// @param location 要删除的下标
SeqList seqList_delete(SeqList seqList,int location){
    if (location < 1 || location > seqList.length) {
        printf("删除位置非法,程序结束\n");
        return  seqList;
    }
    for (int i = location - 1; i<seqList.length - 1; i++) {
        seqList.data[i] = seqList.data[i+1];
    }
    seqList.length --;
    return  seqList;
}

2. Dynamic sequence table:

//#pragma mark -- 删除操作

/// 线性表的插入操作
/// @param seqList 要插入的线性表
/// @param location 要删除第location个元素
///
SeqList seqList_delete(SeqList seqList,int location){
    if (location < 1 || location>seqList.length) {
        printf("删除位置非法,程序退出");
        exit(0);
    }

    for (int i = location - 1; i < seqList.length - 1 ; i++) {
        seqList.elem[i] = seqList.elem[i+1];
    }
    seqList.length--;
    return  seqList;
}

4. Complete code

1. Dynamic sequence table

#include <stdio.h>
#include <stdlib.h> //mac和free函数的原型在<stdlib.h>中


// ---------- 线性表的动态分配顺序存储结构

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

#define list_init_size 9  //线性表存储空间的初始分配量
#define list_initCrement 10 //线性表存储空间的分配增量

typedef struct{
    int * elem; //存储空间基地址
    int length; //当前长度
    int listSize;//当前分配的存储容量(单位:sizeOf(ElemType))
} SeqList;

//#pragma mark -- 初始化线性表(构造一个空表)
SeqList initSeqList(void){
    SeqList seqList;
    seqList.elem = (int *)malloc(list_init_size * sizeof(int));//构造空表
    if (!seqList.elem) {
        printf("==========>>>>>初始化失败,程序退出<<<<<==========\n");
        exit(0);
    }else{
        printf("==========>>>>>链表初始化成功<<<<<==========\n");
    }
    seqList.length = 0;
    seqList.listSize = list_init_size;
    return seqList;
}


//#pragma mark -- 给初始化线性表赋值
SeqList fillInitialSeqList(SeqList seqList){
    for (int i = 0; i < list_init_size; i++) {
        seqList.elem[i] = i;
        seqList.length ++;
    }
    return seqList;
}

//#pragma mark -- 打印函数
void printSeqList(SeqList seqList){
//    printf("\n==========>>>>>\t链表打印开始\t<<<<<==========\n");
    for (int i = 0; i < seqList.length; i++) {
        printf("%d\t",seqList.elem[i]);
    }
//    printf("\n==========>>>>>\t链表打印结束\t<<<<<==========\n");
}

//#pragma mark -- 插入操作

/// 线性表的插入操作
/// @param seqList 要插入的线性表
/// @param location 插入位置
/// @param value 要插入的值
SeqList seqList_insert(SeqList seqList,int location,int value){
    if (location <1 || location>seqList.length+1) {
        printf("插入失败,程序退出");
        exit(0);
    }
    if (seqList.length > seqList.listSize) {//当前存储空间已满 重新分配存储空间
        int * newbase = (int *)malloc(sizeof(int)*(seqList.length + list_initCrement));
        if (!newbase) {
            printf("存储空间分失败,程序退出");
            exit(0);
        }
        seqList.elem = newbase;
        seqList.listSize += list_initCrement;
    }
    for (int i = seqList.length - 1; i >= location - 1 ; i--) {
        seqList.elem[i+1] = seqList.elem[i];
    }
    seqList.elem[location-1] = value;
    seqList.length++;
    return  seqList;
}




//#pragma mark -- 删除操作

/// 线性表的插入操作
/// @param seqList 要插入的线性表
/// @param location 要删除第location个元素
///
SeqList seqList_delete(SeqList seqList,int location){
    if (location < 1 || location>seqList.length) {
        printf("删除位置非法,程序退出");
        exit(0);
    }

    for (int i = location - 1; i < seqList.length - 1 ; i++) {
        seqList.elem[i] = seqList.elem[i+1];
    }
    seqList.length--;
    return  seqList;
}





int main(int argc, char const *argv[])
{
    SeqList seqList = initSeqList();
    seqList = fillInitialSeqList(seqList);
    printf("==========>>>>>\t初始的线性表\t<<<<<==========\n");
    printf("线性表长度:%d\n",seqList.length);
    printSeqList(seqList);
//    seqList = seqList_insert(seqList,8,9);
//    printf("==========>>>>>\t插入后的线性表\t<<<<<==========\n");
//    printSeqList(seqList);
    
    seqList = seqList_delete(seqList,4);
    printf("==========>>>>>\t删除后的线性表\t<<<<<==========\n");
    printSeqList(seqList);
    return 0;
}


2. Static sequence table

#include <stdio.h>
#include <stdlib.h> //mac和free函数的原型在<stdlib.h>中

#define maxSize 100


typedef struct SeqList{
    int data[maxSize] ;//值域
    int length;
}SeqList;



SeqList initSeqList(void){
    SeqList seqList ;
    seqList.length = 0;
    return  seqList;
}

SeqList randomSeqList(SeqList seqLlist){
    for (int i = 0; i<seqLlist.length; i++) {
        printf("请输入第%d个数据元素的值:\n",i+1);
        scanf("%d",&seqLlist.data[i]);
    }
    printf("当前线性表表长:%d\n",seqLlist.length);

    return seqLlist;
}

void printSeqList(SeqList seqList){
    for (int i = 0; i<seqList.length; i++) {
        printf("%d\t",seqList.data[i]);
    }
    printf("\n");
}

/// 顺序表的插入操作
/// @param location 插入位置
/// @param value 插入的值
SeqList seqList_insert(SeqList seqList,int location,int value){
    if (location <1 || location > seqList.length + 1) {
        printf("插入位置非法,程序结束\n");
        return  seqList;
    }
    for (int i = seqList.length -1; i >= location - 1 ; i--) {
        seqList.data[i+1] = seqList.data[i];
    }
    seqList.data[location - 1] = value;
    seqList.length ++;
    return  seqList;
}

/// 顺序表的删除操作
/// @param seqList 要操作的顺序表
/// @param location 要删除的下标
SeqList seqList_delete(SeqList seqList,int location){
    if (location < 1 || location > seqList.length) {
        printf("删除位置非法,程序结束\n");
        return  seqList;
    }
    for (int i = location - 1; i<seqList.length - 1; i++) {
        seqList.data[i] = seqList.data[i+1];
    }
    seqList.length --;
    return  seqList;
}

int main(int argc, const char * argv[]) {
    SeqList seqList =initSeqList();
    int length;
    printf("请输入顺序表的表长:\n");
    scanf("%d",&length);
    seqList.length = length;
    seqList = randomSeqList(seqList);
    printf("==========>>>>>\t初始顺序表\t<<<<<==========\n");
    printSeqList(seqList);
    printf("==========>>>>>\t插入操作之后的线性表\t<<<<<==========\n");
    seqList = seqList_insert(seqList,3,0);
    printSeqList(seqList);
    printf("==========>>>>>\t删除操作之后的线性表\t<<<<<==========\n");
    seqList = seqList_delete(seqList,4);
    printSeqList(seqList);
    return 0;
}

V. Summary

        During the operation of the sequence table above, when we perform an insert operation, we need to keep moving data elements. In the above example, when we insert a data element at the first position of the linear table, we need to move the second element and subsequent elements. Assuming that the length of the linear table is n, the position we need to insert is i, and by analogy, when we want to insert a data element before the i-th element, we need to move n-i+1 elements. Assuming that the probability of inserting elements at any position in the linear table is the same, we can calculate that when we need to perform an insertion operation, the average value of the data elements we need to move is n/2.

        In the same way, we can also infer that when we delete the linear table, the average value of the data elements that need to be moved is n-1/2.

        From this we can draw a conclusion that in the sequential table, we insert or delete an element, on average, we need to move the general elements in the linear table. In this case, when deleting or inserting operations on the sequence table, the time is mainly spent on the movement of data elements. The number of data elements to be moved depends on the position (subscript) of the data element to be deleted or inserted.

Guess you like

Origin blog.csdn.net/ZCC361571217/article/details/120601743