数据结构之顺序表详解

在计算机科学中,数据结构是处理和组织数据的方法和技术。顺序表是一种常见的线性表数据结构,它基于数组实现,提供了快速的随机访问能力。本文将详细介绍顺序表的定义、特点以及常见操作。

1. 顺序表的定义与特点

顺序表是一种线性表的实现方式,它使用一块连续的内存空间存储元素,并通过下标来访问和操作元素。顺序表具有以下特点:

  1. 连续存储:顺序表使用数组来存储元素,数组中的元素在内存中是连续存储的。
  2. 随机访问:由于元素在内存中连续存储,可以通过下标直接访问任意位置的元素,具有快速的随机访问能力。
  3. 插入和删除的复杂度较高:在顺序表中插入和删除元素时,需要移动其他元素以保持顺序,因此插入和删除的时间复杂度较高。
  4. 固定长度:顺序表的长度是固定的,需要预先分配足够的内存空间来存储元素。

2. 顺序表的操作

2.1 构造顺序表

顺序表在C语言中无法用现有的类型来定义,故需要使用构造类型进行构造出顺序表。

当构造顺序表时,您需要先定义一个结构体来表示顺序表,并分配足够的内存空间来存储元素。

示例代码如下:

#define MAX_SIZE 100 // 宏替换
struct SequentialList {
    int data[MAX_SIZE];//MAX_SIZE是一个常量,表示数组空间的大小
    int num;  // 当前顺序表中的元素个数
    int size;//当前所申请数组空间的大小
};

在上面的示例中,我们首先定义了一个结构体 SequentialList,其中包含一个数组 data 用于存储元素,以及一个整型变量 num 表示当前顺序表中的元素个数和size表示数组所能存储的大小。

2.2 创建顺序表

当构造出顺序表结构后,就要创建顺序表,顺序表的创建 即顺序表初始化,示例代码如下:

struct SequentialList * create()
{
    //调用malloc函数申请空间
    struct SequentialList *p = malloc(sizeof(struct SequentialList));
    p->num = 0;//新创建的顺序表元素为0
    p->size = MAX_SIZE;//构造中数组的大小
    return p;
}

在上述示例中,函数 create() 使用 malloc() 函数为顺序表分配了足够的内存空间,并将其地址赋给指针 p。然后,通过 p->num 将顺序表的元素个数初始化为 0,p->size记录了顺序表中能存储的最大元素个数,并返回指针 p

2.2 判断顺序表是否为空

判断顺序表是否为空可以通过判断顺序表的个数是否为 0 来实现。示例代码如下:

// 判断顺序表是否为空
int isEmpty(struct SequentialList* p) {
    return p->num == 0;
}

2.3 判断顺序表是否已满

判断顺序表是否已满可以通过判断个数是否达到最大个数来实现。示例代码如下:

// 判断顺序表是否已满
int isFull(struct SequentialList* p) {
    return p->num == p->size;
}

2.4 获取顺序表的长度

获取顺序表的长度即为获取当前顺序表中元素的个数。示例代码如下:

// 获取顺序表的长度
int getLength(struct SequentialList* p) {
    return p->num;
}

2.5 在指定位置插入元素

顺序表在进行插入和删除时,复杂度较高,故理解顺序表的插入和删除过程是非常有必要的,在顺序表的指定位置插入元素时,防止因插入而破坏顺序表逻辑结构(线性结构,唯一前驱,唯一后继)需要将插入位置之后的元素依次后移,并将新元素插入到指定位置。故如何移动,是我们要特别注意的,从插入元素的位置开始依次往后移动,那么这样移动就会造成前面所移动的值覆盖后面的值(在未插入前,顺序表是一个接一个的,当插入元素时就会破坏这种结构,要插入位置的空间是已经被占用的,且顺序表空间是连续的,当这个位置向后移动时就会覆盖原来空间的值,从而破坏顺序表结构),这种移动方式是行不通的,那我们要怎么去移动才能保证不会破坏顺序表结构,我们这样找到往后移的位置是没有值(后移位置的空间存在且没有值),通过这样分析我们可以得到顺序表最后一个元素(顺序表数组空间允许下)往后移是不会覆盖顺序表的值,故当顺序表未满时进行插入就需要从顺序表尾开始依次往后移,直到移动到要插入元素位置时进行插入。

顺序表满不进行插入。

 

示例代码如下:

// 在指定位置插入元素
void insert(struct SequentialList* p, int position, int element) {
    if (isFull(p)) {
        printf("顺序表已满,无法插入元素。\n");
        return;
    }
    if (position < 0 || position > list->size) {
        printf("插入位置不合法。\n");
        return;
    }
    // 将插入位置之后的元素后移
    for (int i = p->num - 1; i >= position; i--) {
        list->data[i + 1] = list->data[i];
    }
    // 插入新元素
    p->data[position] = element;
    p->num++;
}

2.6 删除指定位置的元素

删除过程相对于插入过程就要简单一些,删除过程就是将要删除的元素进行覆盖进行,即只要将删除元素的后一个元素前移就可以进行将删除元素覆盖,保证顺序表结构,后面元素也要依次前移。当然顺序表为空不进行删除。即删除顺序表的指定位置元素需要将删除位置之后的元素依次前移,并更新顺序表的长度。

 

示例代码如下:

// 删除指定位置的元素
void delete(struct SequentialList* p, int position) {
    if (isEmpty(p)) {
        printf("顺序表为空,无法删除元素。\n");
        return;
    }
    if (position < 0 || position >= p->num) {
        printf("删除位置不合法。\n");
        return;
    }
    // 将删除位置之后的元素前移
    for (int i = position; i < p->num - 1; i++) {
        p->data[i] = p->data[i + 1];
    }
    p->num--;
}

2.7 获取指定位置的元素

获取顺序表的指定位置元素即为通过下标访问对应位置的元素。示例代码如下:

// 获取指定位置的元素
int getElement(struct SequentialList* p, int position) {
    if (position < 0 || position >= p->num) {
        printf("访问位置不合法。\n");
        return -1;  // 返回一个特殊值表示出错
    }
    return p->data[position];
}

2.8遍历顺序表元素

通过循环输出顺序表元素,示例代码如下:

void show(struct SequentialList *p)
{
        for(int i = 0;i < p->num;i++)
        {
                printf("%d ",p->data[i]);
        }
        printf("\n");
}

总体代码

#define MAX_SIZE 100 // 宏替换

//构造顺序表
struct SequentialList {
    int data[MAX_SIZE];//MAX_SIZE是一个常量,表示数组空间的大小
    int num;  // 当前顺序表中的元素个数
    int size;//当前所申请数组空间的大小
};

//创建顺序表
struct SequentialList * create()
{
    //调用malloc函数申请空间
    struct SequentialList *p = malloc(sizeof(struct SequentialList));
    p->num = 0;//新创建的顺序表元素为0
    p->size = MAX_SIZE;//构造中数组的大小
    return p;
}

// 判断顺序表是否为空
int isEmpty(struct SequentialList* p) {
    return p->num == 0;
}

// 判断顺序表是否已满
int isFull(struct SequentialList* p) {
    return p->num == p->size;
}

// 获取顺序表的长度
int getLength(struct SequentialList* p) {
    return p->num;
}

// 在指定位置插入元素
void insert(struct SequentialList* p, int position, int element) {
    if (isFull(p)) {
        printf("顺序表已满,无法插入元素。\n");
        return;
    }
    if (position < 0 || position > list->size) {
        printf("插入位置不合法。\n");
        return;
    }
    // 将插入位置之后的元素后移
    for (int i = p->num - 1; i >= position; i--) {
        list->data[i + 1] = list->data[i];
    }
    // 插入新元素
    p->data[position] = element;
    p->num++;
}

// 删除指定位置的元素
void delete(struct SequentialList* p, int position) {
    if (isEmpty(p)) {
        printf("顺序表为空,无法删除元素。\n");
        return;
    }
    if (position < 0 || position >= p->num) {
        printf("删除位置不合法。\n");
        return;
    }
    // 将删除位置之后的元素前移
    for (int i = position; i < p->num - 1; i++) {
        p->data[i] = p->data[i + 1];
    }
    p->num--;
}

// 获取指定位置的元素
int getElement(struct SequentialList* p, int position) {
    if (position < 0 || position >= p->num) {
        printf("访问位置不合法。\n");
        return -1;  // 返回一个特殊值表示出错
    }
    return p->data[position];
}

//遍历
void show(struct SequentialList *p)
{
        for(int i = 0;i < p->num;i++)
        {
                printf("%d ",p->data[i]);
        }
        printf("\n");
}

int main() {
    struct SequentialList* p = create();  // 创建顺序表并获取指针
    // 此时,顺序表已经创建完成,并可以进行操作
    // 例如,可以通过 p->data 访问数组,通过 p->length 访问元素个数
    
    for(int i = 1;i < 11;i++)
    {
        insert(p,i,i);//插入元素(循环插入1-10)
    }
    show(p);//遍历
    delete(p,5);//删除下标为5的元素
    show(p);
    return 0;
}

3. 总结

顺序表是一种基于数组实现的线性表数据结构,具有快速的随机访问能力。它适用于需要频繁随机访问元素的场景,但插入和删除操作的效率相对较低。通过本文的介绍,您应该对顺序表的定义、特点以及常见操作有了更深入的了解。

希望本文对您理解顺序表有所帮助,感谢您的阅读!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值