转载-C语言顺序表

本文深入探讨了线性表的顺序存储结构,包括其定义、特点及在C语言中的实现方式。详细介绍了顺序表的基本操作,如初始化、求长度、查找、插入、删除等,并提供了完整的代码示例。

线性表的顺序存储

线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表在逻辑结构上相邻的元素存储在连续的物理存储单元中,即:通过数据元素物理存储的连续性来反应元素之间逻辑上的相邻关系。采用顺序存储结构存储的线性表通常简称为顺序表。
顺序存储的线性表的特点:
◆ 线性表的逻辑顺序与物理顺序一致;
◆ 数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。

顺序表的线性存储示意图

假设线性表中有n个元素,每个元素占k个存储单元,第一个元素的地址为Loc(a1),则第i个元素的地址Loc(ai):
在这里插入图片描述
Loc(ai) = Loc(a1) + (i-1) * k;
其中Loc(a1)称为基地址。

C语言定义线性表的顺序存储结构

#define ListSize 100      //线性表的最大长度
typedef int DataType;

typedef struct
{
    DataType data[ListSize];   //用数组存储线性表中的元素
    DataType length;           //顺序表中元素的个数
}SeqList, *PSeqList;

DataType是数据元素类型,可以根据需要定义,可以使用SeqList定义数据表类型变量,使用*PSeqList定义数据表指针变量;

顺序表的基本操作

(1) 顺序表的初始化

顺序表的初始化就是把顺序表 初始化为空的顺序表;只需把顺序表的长度length置为0即可;

void InitList(PSeqList L)
{
    if (L == NULL)
    {
        return;
    }
    L->length = 0;
}

(2)求顺序表的长度

顺序表的长度就是就顺序表中的元素的个数,由于在插入和删除操作中都有对数据表的长度进行修改,所以求表长只需返回length的值即可;

int LengthList(PSeqList L)
{
    if (L == NULL)
    {
        return 0;
    }
    return L->length;
}

(3)按序号查找

查找顺序表中第i个元素的值(按序号查找),如果找到,将将该元素值赋给e。查找第i个元素的值时,首先要判断查找的序号是否合法,如果合法,返回第i个元素对应的值。

int GetData(PSeqList L, int i)
{
    if (L->length < 1 || (L->length > LengthList(L)))
    {
        return 0;
    }
    //数据元素的序号从1开始,数组下表从0开始,第i个元素对应的数组下标为i-1;
    return L->data[i - 1];
}

(4)插入操作

在数据表的第i个位置插入元素,在顺序表的第i个位置插入元素e,首先将顺序表第i个位置的元素依次向后移动一个位置,然后将元素e插入第i个位置,移动元素要从后往前移动元素,即:先移动最后一个元素,在移动倒数第二个元素,依次类推;插入元素之前要判断插入的位置是否合法,顺序表是否已满,在插入元素之后要将表长L->length++;

int InsList(PSeqList L, int i, DataType e)
{

    //判断插入位置是否合法
    if (i < 1 || L->length >(LengthList(L) + 1))
    {
        printf("插入位置不合法!\n");
        return 0;
    }
    //判断顺序表是否已满
    else if (L->length >= ListSize)
    {
        printf("顺序表已满,不能插入!\n");
        return 0;
    }
    else
    {
        for (k = i; k <= L->length; k--)
        {
            L->data[k + 1] = L->data[k];
        }
        L->data[i - 1] = e;
        L->length++;   //数据表的长度加1
        return 1;
    }
    return 0;
}

(5) 删除操作

删除表中的第i个元素e,删除数据表中的第i个元素,需要将表中第i个元素之后的元素依次向前移动一位,将前面的元素覆盖掉。移动元素时要想将第i+1个元素移动到第i个位置,在将第i+2个元素移动i+1的位置,直到将最后一个元素移动到它的前一个位置,进行删除操作之前要判断顺序表是否为空,删除元素之后,将表长L->length–;

int DelList(PSeqList L, DataType i, DataType* e)
{
    if (L->length < 1)
    {
        printf("表为空!\n");
        return  0;
    }
    *e = L->data[i - 1];
    for (k = i; k < L->length; k++)
    {
        L->data[k - 1] = L->data[k];
    }
    L->length--;
    return *e;
}

(6)按内容查找

查找数据元素e在表中的位置,可以从表头开始一直遍历表中元素,如果找到与要查找元素e相等的元素,则返回元素在表中的位置,数组下标从0开始,则元素在表中对应的位置序号值应为对应数组下标加1,没有找到则返回0;

int Locate(PSeqList L, DataType e)
{
    for (k = 0; k < L->length; k++)
    {
        if (L->data[k] == e)
        {
            //k为e对应的数组下标,在表中对应序号应为k+1
            return k + 1;
        }
    }
    return 0;
}

(7)头插

头插,即在表头插入元素e,在表头插入元素,需要将表中的元素依次后移一位,然后将要插入的元素e赋给数字的首元素,执行插入操作后将表长L->length++;需要注意的是移动元素要从顺序表的最后一个元素开始移动,如果从第1个元素开始移动,会使得第1个元素的值覆盖第2个元素的值,然后把第二个元素后移则会使第2个元素的值(原来第1个元素值)覆盖第3个元素的值,依次类推,最后出插入元素外,其余元素值均为原顺序表中第一个元素的值。

void PushFront(PSeqList L, DataType e)
{
    if (L->length == ListSize)
    {
        printf("顺序表已满,不能插入!\n");
    }
    //将表中元素依次后移一位
    for (k = L->length; k > 0; k--)
    {
        L->data[k] = L->data[k - 1];
    }
    //插入元素
    L->data[0] = e;
    L->length++;
}

(8)头删

删除顺序表中的第一个元素,只要将顺序表中的元素从第2个开始,依次向前移动1位,覆盖原来顺序表中元素对应位置的前一个值,在删除元素之前要判断顺序表是否为空,删除顺序表元素之后将顺序表长度L->length–;

void PopFront(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("顺序表为空\n");
    }
    for (k = 1; k <= L->length - 1; k++)
    {
        L->data[k - 1] = L->data[k];
    }
    L->length--;
}

(9)尾插

在顺序表表尾插入元素e,L->data[L->length] = e;将元素e的值赋给顺序表中最后一个元素的下一个元素;尾插操作,需要判断顺序表是否已满,尾插后将顺序表长度L->length++;

void PushBack(PSeqList L, DataType e)
{
    if (L->length == ListSize)
    {
        printf("顺序表已满,不能插入!\n");
    }
    L->data[L->length] = e;
    L->length++;
}

(10) 尾删

删除表尾元素,只需将顺序表的长度减1,类似于出栈操作,栈顶指针top –。

void PopBack(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("表为空!\n");
    }
    L->length--;

}

(11) 清空顺序表

清空顺序表就是将表中的元素删除。删除表中的元素只需将表的长度置为0。

void ClearList(PSeqList L)
{
    L->length = 0;
}

(12)判断表是否为空

如果顺序表的长度为0,则顺序表为空,返回1,否则,返回0;

int EmptyList(PSeqList L)
{
    if (L->length == 0)
    {
        return 1;
    }
    return 0;
}

(13)打印表中元素

依次打印顺序表中的元素,如果顺序表为空则输出提示。

void PrintList(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("表为空!\n");
        return;
    }
    for (k = 0; k < L->length; k++)
    {
        printf("%-3d", L->data[k]);
    }
    printf("\n");
}

顺序表的基础操作完整代码
SeqList.h数据结构的定义和基本操作函数声明

#pragma once

#define ListSize 100      //线性表的最大长度
typedef int DataType;

typedef struct
{
    DataType data[ListSize];   //用数组存储线性表中的元素
    DataType length;           //顺序表的长度
}SeqList, *PSeqList;

void InitList(PSeqList L);  //顺序表的初始化操作
int LengthList(PSeqList L); //求顺序表的长度
int GetData(PSeqList L, int i); //返回数据表中第i个元素的值
int InsList(PSeqList L, int i, DataType e);   //在顺序表的第i个位置插入元素
int DelList(PSeqList L, DataType i, DataType* e); //删除顺序表L的第i个数据元素
int Locate(PSeqList L, DataType e); //查找数据元素e在表中的位置
void PushFront(PSeqList L, DataType e); //头插,在表头插入元素e
void PopFront(PSeqList L);    //头删,删除表中的第一个元素
void PushBack(PSeqList L, DataType e);  //尾插,在表尾插入元素e
void PopBack(PSeqList L); //尾删,删除表尾元素
void ClearList(PSeqList L);  //清空顺序表
int EmptyList(PSeqList L);   //判断顺序表是否为空
void PrintList(PSeqList L);  //打印表中元素

SeqList.c 函数的具体实现

#include <stdio.h>
#include "SeqList.h"

int k = 0;  //全局变量,用于作部分操作的循环变量
//初始化顺序表
void InitList(PSeqList L)
{
    if (L == NULL)
    {
        return;
    }
    L->length = 0;
}

//求顺序表的长度

int LengthList(PSeqList L)
{
    if (L == NULL)
    {
        return 0;
    }
    return L->length;
}

//返回数据表中第i个元素的值
int GetData(PSeqList L, int i)
{
    if (L->length < 1 || (L->length > LengthList(L)))
    {
        return 0;
    }
    //数据元素的序号从1开始,数组下表从0开始,第i个元素对应的数组下标为i-1;
    return L->data[i - 1];
}

//在L中第i个位置,插入新的数据元素e

int InsList(PSeqList L, int i, DataType e)
{

    //判断插入位置是否合法
    if (i < 1 || L->length >(LengthList(L) + 1))
    {
        printf("插入位置不合法!\n");
        return 0;
    }
    //判断顺序表是否已满
    else if (L->length >= ListSize)
    {
        printf("顺序表已满,不能插入!\n");
        return 0;
    }
    else
    {
        for (k = i; k <= L->length; k--)
        {
            L->data[k + 1] = L->data[k];
        }
        L->data[i - 1] = e;
        L->length++;   //数据表的长度加1
        return 1;
    }
    return 0;
}

//删除L的第i个数据元素

int DelList(PSeqList L, DataType i, DataType* e)
{
    if (L->length < 1)
    {
        printf("表为空!\n");
        return  0;
    }
    *e = L->data[i - 1];
    for (k = i; k < L->length; k++)
    {
        L->data[k - 1] = L->data[k];
    }
    L->length--;
    return *e;
}

//查找e在表中的位置

int Locate(PSeqList L, DataType e)
{
    for (k = 0; k < L->length; k++)
    {
        if (L->data[k] == e)
        {
            //k为e对应的数组下标,在表中对应序号应为k+1
            return k + 1;
        }
    }
    return 0;
}

//头插,在表头插入元素e

void PushFront(PSeqList L, DataType e)
{
    if (L->length == ListSize)
    {
        printf("顺序表已满,不能插入!\n");
    }
    //将表中元素依次后移一位
    for (k = L->length; k > 0; k--)
    {
        L->data[k] = L->data[k - 1];
    }
    //插入元素
    L->data[0] = e;
    L->length++;
}

//头删,删除顺序表中的第一个元素,把顺序表中的元素依次往前移动一位

void PopFront(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("顺序表为空,不能插入!\n");
    }
    for (k = 1; k <= L->length - 1; k++)
    {
        L->data[k - 1] = L->data[k];
    }
    L->length--;
}

//尾插
void PushBack(PSeqList L, DataType e)
{
    if (L->length == ListSize)
    {
        printf("顺序表已满,不能插入!\n");
    }
    L->data[L->length] = e;
    L->length++;
}


//尾删
void PopBack(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("表为空!\n");
    }
    L->length--;

}

//清空顺序表
void ClearList(PSeqList L)
{
    L->length = 0;
}

//判断表是否为空

int EmptyList(PSeqList L)
{
    if (L->length == 0)
    {
        return 1;
    }
    return 0;
}

//打印表中元素

void PrintList(PSeqList L)
{
    if (EmptyList(L))
    {
        printf("表为空!\n");
        return;
    }
    for (k = 0; k < L->length; k++)
    {
        printf("%-3d", L->data[k]);
    }
    printf("\n");
}

mian.c函数的简单测试代码

#include <stdio.h>
#include <Windows.h>
#include "SeqList.h"
int main()
{
    SeqList L;
    DataType data;
    //初始化顺序表
    InitList(&L);
    //在表中插入元素
    printf("依次在表中插入元素(1,2,3,4,5):\n");
    InsList(&L, 1, 1);
    InsList(&L, 2, 2);
    InsList(&L, 3, 3);
    InsList(&L, 4, 4);
    InsList(&L, 5, 5);

    //打印表中元素
    printf("表中元素有:\n");
    PrintList(&L);
    //头插
    printf("在表头依次插入元素,6,7:\n");
    PushFront(&L, 6);
    PushFront(&L, 7);
    //尾插
    printf("在表尾依次插入元素,8,9:\n");
    PushBack(&L, 8);
    PushBack(&L, 9);
    printf("表中元素有:\n");
    PrintList(&L);
    //头删
    printf("头删一个元素:\n");
    PopFront(&L);
    //尾删
    printf("尾删一个元素:\n");
    PopBack(&L);
    //输出表中第4个元素值
    PrintList(&L);
    printf("表中第4个元素值为:\n%d\n",GetData(&L, 4));
    //查找表中第 i个元素的位置
    printf("元素2在表中的位置为:\n");
    printf("%d\n",Locate(&L, 2));
    //删除表中第2个元素对应的值
    printf("删除表中第2个元素:%d\n", DelList(&L, 2, &data));
    printf("顺序表的长度为:%d\n", LengthList(&L));
    printf("表中元素为:\n");
    PrintList(&L);
    //printf("删除的元素值为:%d\n", data);
    //清空顺序表
    ClearList(&L);
    PrintList(&L);
    system("pause");
    return 0;
    }
--------------------- 

作者:LiuBo_01
来源:优快云
原文:https://blog.youkuaiyun.com/liubo_01/article/details/80186552

线性表(List):零个或多个数据元素的有限序列 线性表的顺序存储结构简称为顺序表(sequential list) 数组大小MaxSize一般定义为一个整型常量。如果估计一个线性表不会超过50个元素,则可以把MaxSize定义为50: #define MaxSize 50 在声明线性表的顺序存储类型时,定义一个data数组来存储线性表中的所有元素,还定义一个整型变量length来存储线性表的实际长度,并采用结构体类型SqList表示如下: typedef struct { ElemType data[MaxSize]; //数组,存储数据元素 int length; //存放顺序表的长度 } SqList; //顺序表的类型 1 2 3 4 注意:线性表元素的逻辑序号是从1开始的,而对应顺序表的data[]数组下标是从0开始的(物理序号) 定义方式为:SqList *L 采用顺序表指针,主要是为了方便顺序表的释放算法设计,并且在函数之间传递顺序表指针时会节省为形参分配的空间。 L=(SqList *)malloc(sizeof(SqList)); 由sizeo分配所需空间大小,malloc开辟(new)sizeof那么大的空间,这是指向SqList的指针,最后把该地址交给了指针L 调用CreateList算法创建好L所指的顺序表后,需要回传给对应的实参,也就是说,L是输出型参数,所有在形参上L的前面需要加上引用符“&” 参考博客 [1].指针 [2].动态内存分配与指向它的指针变量 [3].SqList *&L与SqList *L的区别 Code: #include <stdio.h> #include <malloc.h> #define MaxSize 50 //存储空间初始分配量 typedef char ElemType; //ElemType类型根据实际情况而定,这里为char typedef struct { ElemType data[MaxSize]; //数组,存储数据元素 int length; //存放顺序表的长度 } SqList; //顺序表的类型 /*建立顺序表CreateList,将数组a中的每个元素依次放入到顺序表中,并将n赋给顺序表的长度 由a中的n个元素建立顺序表*/ void CreateList(SqList *&L,ElemType a[],int n)//形参 { L=(SqList *)malloc(sizeof(SqList)); //相当于new,出来一个sizeof这么大的空间,把它指向SqList这样的一个指针,把地址交给了L for (int i=0;i<n;i++) //放入数据 L->data[i]=a[i]; L->length=n; //设置L的长度n } //1、初始化线性表InitList,构造一个空的线性表L,只需分配线性表的存储空间并将length域设置为0即可 void InitList(SqList *&L) { L=(SqList *)malloc(sizeof(SqList)); L->length=0; } //2、销毁线性表DestroyList,释放线性表L占用的内存空间 void DestroyList(SqList *&L) { free(L); //释放L所指的顺序表空间 } //3、判断线性表是否为空表ListEmpty, 返回一个布尔值是否为空表。若L为空表,则返回true,否则返回false。 bool ListEmpty(SqList *L) { return(L->length==0); } //4、求线性表的长度ListLength,返回顺序表L的长度,返回length域的值即可 int ListLength(SqList *L) { return(L->length); } //5、输出线性表DispList void DispList(SqList *L) { for (int i=0;i<L->length;i++) printf("%d ",L->data[i]); printf("\n"); } //6、求线性表中的某个数据元素值GetElem,该运算用引用型参数e返回L中第i(1<=i<=n)个元素的值 bool GetElem(SqList *L,int i,ElemType &e) { if (i<1 || i>L->length) return false; //参数i错误时返回false e=L->data[i-1]; //元素值 return true; //成功找到元素时返回true } //7、按元素值查找LocateELem int LocateElem(SqList *L, ElemType e) { int i=0; while (i<L->length && L->data[i]!=e)//i在length域里,而且i里面的元素都不等于e i++; if (i>=L->length) //第一种情况,i都不在范围内 return 0; else return i+1; //找到e后,返回其逻辑序号 } //8、插入数据元素ListInsert,就是五个人,有一个人插进来了,往后移,变六个人了, bool ListInsert(SqList *&L,int i,ElemType e) { int j; if (i<1 || i>L->length+1) //在顺序表L第i(1<=i<=n+1)个位置上插入新元素e return false; //i值不对,返回false i--; //将顺序表逻辑序号转化为物理序号 for (j=L->length;j>i;j--) //将data[i]及后面元素后移一个位置 L->data[j]=L->data[j-1]; //如果线性表长度(1开始)大于数组长度(0开始) L->data[i]=e; //插入元素e L->length++; //顺序表长度增1 return true; //成功插入返回true } /* i=4,表示是第4个元素,但是数组里面是data[3],所以i-- j=5,j>i,原来data[4]是第五个元素'e', 顺序表长度增1,data[5]=e为第六个元素最后一个元素,以此类推。 */ //9、删除数据元素ListDelete bool ListDelete(SqList *&L,int i,ElemType &e) { int j; if (i<1 || i>L->length) //(1<= i <= n) return false; i--; //将顺序表逻辑序号转化为物理序号 e=L->data[i]; //e=L->data[2] for (j=i;j<L->length-1;j++) //j=2;j<5,j++ L->data[j]=L->data[j+1]; //2=3 e=f L->length--; //顺序表长度减1 return true; } int main(){ SqList *L; //定义一个指向SqList的地址,要不然地址怎么过来 InitList(L); // printf("%d",L->length); //测试 ElemType e; printf("顺序表的基本运算如下:\n"); printf("1.初始化顺序表L\n"); InitList(L); printf("2.依次采用尾插法插入a,b,c,d,e元素\n"); ListInsert(L,1,'a'); ListInsert(L,2,'b'); ListInsert(L,3,'c'); ListInsert(L,4,'d'); ListInsert(L,5,'e'); printf("3.输出顺序表:"); DispList(L); printf("4.顺序表L长度=%d\n",ListLength(L)); printf("5.顺序表L为%s\n",(ListEmpty(L)?"空":"非空")); GetElem(L,3,e); printf("6.顺序表L的第3个元素=%c\n",e); printf("7.元素a的位置=%d\n",LocateElem(L,'a')); printf("8.在第4个元素位置上插入f元素\n"); ListInsert(L,4,'f'); printf("9.输出顺序表L:"); DispList(L); printf("10.删除L的第3个元素\n"); ListDelete(L,3,e); printf("11.输出顺序表L:"); DispList(L); printf("12.释放顺序表L\n"); DestroyList(L); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 AI写代码 result: ———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.youkuaiyun.com/weixin_45959708/article/details/119521235这一篇博客怎么样
最新发布
05-27
### 如何评价一篇关于线性表顺序存储结构及其实现的博客文章 要全面评价一篇介绍线性表顺序存储结构(即顺序表)及其C语言实现的博客文章,可以从以下几个方面展开分析: #### 1. **理论基础** 博客是否清晰阐述了线性表的基本概念以及其顺序存储的特点。例如,线性表是一种逻辑结构,具有以下特征:元素个数有限;元素按一定次序排列;除首尾元素外,每个元素只有一个前驱和后继[^3]。如果这些基本概念被清楚解释并辅以实例说明,则可以认为该部分完成得较好。 #### 2. **代码质量** 对于实际编码部分,应关注代码的功能性和可读性。比如,在创建顺序表时,函数`CreatList`的设计考虑到了输入数据量超过预设最大容量的情况,并通过返回值指示操作的成功与否[^4]。这种处理方式体现了良好的编程习惯。另外,代码风格是否统一、变量命名是否有意义也会影响读者的理解体验。 #### 3. **功能覆盖度** 文章提到实现了简单的读、插入和删除等功能[^1]。一个好的教程应该不仅限于此,还可能扩展到更复杂的场景如两顺序表合并等问题[^2]。因此,可以根据文中描述判断作者是否提供了足够的应用场景来帮助初学者掌握这一知识点。 #### 4. **错误纠正与优化建议** 如果发现原文存在任何技术上的不准确性或潜在缺陷,应当指出并向原作者提供改进建议。这不仅能体现评论者的专业水平,也有助于促进共同学习进步。 #### 5. **互动性与开放态度** 原文作者表明自己是一名本科生并且欢迎他人对其工作提出反馈意见。这样的姿态值得肯定,因为它鼓励了一个积极健康的讨论环境。 ```cpp // 示例代码片段展示如何优雅地实现顺序表的部分功能 #include <iostream> using namespace std; const int MAXSIZE = 10; struct SeqList { int data[MAXSIZE]; int length; }; bool Insert(SeqList *L, int pos, int value){ if(L->length >= MAXSIZE || pos<0 ||pos>L->length) return false; for(int i=L->length;i>pos;i--) L->data[i]=L->data[i-1]; L->data[pos]=value; L->length++; return true; } void PrintSeqList(SeqList L){ cout << "["; for(int i=0;i<L.length;i++) cout << L.data[i] << (i!=L.length-1?", ":""); cout << "]"<<endl; } ``` 以上是一个简化版本的例子用于演示目的。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值