1.顺序表概念及特点
顺序表是一种线性数据结构,其特点如下:
-
存储连续:顺序表使用一块连续的内存空间来存储元素,可以通过下标进行随机访问。这种存储方式使得顺序表的访问效率较高。
-
元素有序:顺序表中的元素按照一定的顺序(通常是插入的顺序)排列,每个元素可以通过唯一的下标值进行访问。
-
大小固定:顺序表的大小在创建时就确定,无法动态地改变大小,因此需要提前分配好足够的内存空间。
-
插入和删除效率较低:由于顺序表的大小固定,插入和删除元素时需要进行元素的后移或前移操作,这样的操作效率较低。尤其是在插入和删除元素的中间位置时,需要移动大量元素。
-
随机访问高效:由于元素在顺序表中是连续存储的,并且可以通过下标直接计算出元素的地址,所以随机访问的效率非常高。
-
内存开销大:顺序表需要提前分配足够的内存空间来存储元素,如果未能合理估计元素的数量,可能导致内存的浪费。
综上所述,顺序表适用于元素数量固定、频繁进行随机访问的场景,但插入和删除操作相对较慢,且需要提前预估好元素的数量以避免内存浪费。
另外顺序表分为动态和静态
静态就是给定一个容量
#define N 100
typedef int Datetype;
typedef struct Sequence
{
Datetype array[N]; //定长数组
size_t number; //有效数据的个数
};
下面我们详细讲一下动态顺序表
2.图解
typedef struct Sequence
{
Date_type* a;
int number; //有效数据的个数
int capacity; //顺序表的容量
}KT;
我们要通过a和number对表里数据进行一些接口操作,比如增删查改;根据capacity与number的关系决定是否扩容。
下面是完整的程序:
1.头文件程序
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
typedef int Date_type; //增强程序的可维护性,想要改变数据类型,直接在这里面改就可以
//动态顺序表
typedef struct Sequence
{
Date_type* a;
int number; //有效数据的个数
int capacity; //顺序表的容量
}KT;
//相关接口函数
void Sequence_init(KT* ps); //初始化接口
void Sequence_print(KT* ps);//打印
void Sequence_destory(KT* ps);//销毁
void Sequence_pushback(KT* ps, Date_type x); //尾插
void Sequence_pushfront(KT* ps, Date_type x); //头插
void Sequence_popback(KT* ps); //尾删
void Sequence_popfront(KT* ps); //头删
void Sequence_insert(KT * ps, int pos, Date_type x); //任意位置插入
void Sequence_erase(KT* ps, int pos); //任意位删除
int Sequen_find(KT* ps, Date_type x); //查找
void Sequence_modity(KT* ps, int pos, Date_type x); //
2.函数源文件
#include "sequence.h"
void Sequence_init(KT* ps) //初始化接口
{
ps->a = NULL;
ps->number = 0;
ps->capacity = 0;
}
void Sequence_print(KT* ps)
{
for (int i = 0; i < ps->number; ++i)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
void Sequence_destory(KT* ps)//销毁
{
free(ps->a);
ps->a = NULL;
ps->capacity = ps->number = 0;
}
void Sequence_add_newcapacity(KT*ps)
{
//检查容量是否慢了,满了则增加容量
if (ps->number == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
Date_type* tmp = (Date_type*)realloc(ps->a, newcapacity * sizeof(Date_type));
if (tmp == NULL)
{
printf("realloc failed\n");
exit(-1); //是一个用于终止程序执行的函数。它的参数 -1 是一个返回值,表示程序执行失败或出现错误的情况。
}
else
{
ps->a = tmp;
ps->capacity = newcapacity;
}
}
}
void Sequence_pushback(KT* ps, Date_type x) //尾插
{
//Sequence_add_newcapacity(ps); //这是第一种方式
//ps->a[ps->number] = x;
//ps->number++;
Sequence_insert(ps, ps->number, x); //这是第二种方式,一个意思
}
void Sequence_pushfront(KT* ps, Date_type x) //头插
{
Sequence_add_newcapacity(ps); //这是第一种方式,查看是否需要增容
int end = ps->number - 1;
while (end >= 0) //把表里的数据全部向后移动一位,此时a[0]==a[1],可以放心赋值给a[0];
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[0] = x;
ps->number++;
//Sequence_insert(ps,0,x); //这是第二种方式,一个意思
}
void Sequence_popback(KT* ps) //尾删
{
assert(ps->number > 0);
ps->a[ps->number - 1] = 0;
ps->number--;
//Sequence_erase(ps, ps->number - 1); 第二种方式
}
void Sequence_popfront(KT* ps) //头删
{
assert(ps->number > 0);
int first = 1;
while (first < ps->number)
{
ps->a[first - 1] = ps->a[first]; //全部前移一位
++first;
}
ps->number--;
//Sequence_erase(ps, 0); //第二种方式
}
void Sequence_insert(KT * ps, int pos, Date_type x) //任意位置插入
{
assert(pos <= ps->number); //断言 插入位置得在数据中
Sequence_add_newcapacity(ps);
int end = ps->number - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end]; //从要插入的位置开始全部后移一位;
--end;
}
ps->a[pos] = x;
ps->number++;
}
void Sequence_erase(KT* ps, int pos) //任意位删除
{
assert(pos < ps->number);
int first = pos + 1;
while (first < ps->number) //前移一位
{
ps->a[first - 1] = ps->a[first];
++first;
}
ps->number--;
}
int Sequen_find(KT* ps, Date_type x) //查找
{
for (int i = 0; i < ps->number; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
void Sequence_modity(KT* ps, int pos, Date_type x) //修改某个位置的值
{
assert(pos < ps->number);
ps->a[pos] = x;
}
3.测试文件(可以接着自行测试)
#include "sequence.h"
void Test_sequence()
{
KT index;
Sequence_init(&index); //传地址是为了直接对顺序表进行修改,如果直接传index,那么将会操作index的副本
//将不会对index产生任何影响
Sequence_pushback(&index, 0);
Sequence_pushback(&index, 1);
Sequence_pushback(&index, 2);
Sequence_pushback(&index, 3);
Sequence_pushback(&index, 4);
Sequence_pushback(&index, 5);
Sequence_pushback(&index, 6);
Sequence_print(&index);//打印
Sequence_destory(&index);//销毁
}
int main()
{
Test_sequence();
return 0;
}
大家有疑问的话欢迎交流。