线性表 linear list
线性表是具有 相同数据类型的n(n≥0)个数据元素的有限序列,其中n为表长,当n=0时,线性表是一个空表。
若用L命名线性表,则其一般表示为L = (a1, a2, … , ai , ai+1, … , an)
注:
ai是线性表中的“第i个”元素线性表中的位序 a1是表头元素;
an是表尾元素。
除第一个元素外,每个元素有且仅有一个直接前驱;除最后一个元素外,每个元素有且仅有一个直接后继
顺序表的定义
用顺序存储的方式实现线性表的顺序存储。
把逻辑上相邻的元素,存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
顺序表的基本操作
顺序表的实现:静态分配
//顺序表的实现-静态分配
typedef struct {
int data[MaxSize];
//ElemType data[MaxSize]
int length; //顺序表当前长度
}SqList; //sequence
//初始化一个顺序表
void InitList(SqList &L){
L.length = 0; //顺序表初始长度为0
}
//创建顺序表,输入元素
bool CreateList(SqList &L, int n)
{
if (n<0 || n>MaxSize) return false;//非法判定
for (int i = 0; i < n; i++)
{
printf("请输入顺序表第%d个元素:",i+1);
scanf("%d", &L.data[i]);
L.length++;
}
return true;
}
ElemType是一个抽象的概念,表示“数据元素的类型”,表示我们所要使用的数据元素应有的类型。
数据元素的大小:
sizeof(ElemType)
需要什么类型可以对它重定义:
typedef int ElemType;//定义ElemType为int类型
顺序表的实现:动态分配
#define InitSize 10 //定义初始长度
typedef struct {
int *data;
int MaxSize;
int length; //顺序表当前长度
}SeqList;
顺序表的实现
- 随机访问,在**O(1)**时间内找到任一元素
- 每个节点只存储数据元素**(区分链表)**
- 拓展容量不方便,,时间复杂度较高
- 插入、删除操作不方便
向顺序表中插入元素
在表L中的第i个位置上插入指定元素e
void ListInsert(SqList &L,int i,int e){
for(int j=L.length;j>=i;j--){
//将i和之后的元素后移
L.data[j]=L.data[j-1];
}
//在位置i(对应数组下标i-1)放入e
L.data[i-1]=e;
L.length++;
}
插入函数也可定义为bool函数
平均时间复杂度:O(n)
从顺序表中删除元素
删除表L中第i个位置的元素,并用e返回删除元素的值
bool ListDelete(SqList &L, int i,int &e){
if(i<1 || i>L.length){
return false;
}
e = L.data[i-1];
//将被删除的元素赋值给e
for(int j = i; j < L.length; j++){
//将第i个位置后的元素前移
L.data[j-1] = L.data[j];
}
L.length--;
return true;
}
平均时间复杂度:O(n)
顺序表的按位查找
获取表L中第i个位置的元素的值
int GetElem(SqList L, int i){
return L.data[i-1];
}
由于顺序表的各个数据元素在内存中连续存放, 因此可以根据起始地址和数据元素大小立即找到 第 i 个元素
时间复杂度:O(1)
顺序表的按值查找
在表L中查找具有给定关键字值的元素
int LocateElem(SeqList L,int e){
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
//数组下标为i的元素值等于e,返回其位序i+1
return 0;
//退出循环,说明查找失败
}
平均时间复杂度:O(n)
代码实现
#include <stdio.h>
#define MaxSize 10
typedef struct {
int data[MaxSize];
int length; //线性表当前长度
}SqList;
//初始化线性表,构造一个空的顺序表
void InitList(SqList &L){
L.length = 0;
}
//创建顺序表,输入元素
bool CreateList(SqList &L, int n)
{
if (n<0 || n>MaxSize) return false;//非法判定
for (int i = 0; i < n; i++)
{
printf("请输入顺序表第%d个元素:",i+1);
scanf("%d", &L.data[i]);
L.length++;
}
return true;
}
//插入 将e插入到第i个位置上
void ListInsert(SqList &L,int i,int e){
for(int j=L.length;j>=i;j--){
//将i和之后的元素后移
L.data[j]=L.data[j-1];
}
//在位置i(对应数组下标i-1)放入e
L.data[i-1]=e;
L.length++;
}
//删除 删除第i个元素并把值赋给e返回
bool ListDelete(SqList &L, int i,int &e){
if(i<1 || i>L.length){
return false;
}
//将被删除的元素赋值给e
e = L.data[i-1];
for(int j = i; j < L.length; j++){
//将第i个位置后的元素前移
L.data[j-1] = L.data[j];
}
L.length--;
return true;
}
//得到顺序表中的第i个数字
int GetElem(SqList L, int i){
return L.data[i-1];
}
//查找 查找第一个值为e的元素返回其位置(第i+1个)
int LocateElem(SqList L,int e){
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
return 0;
}
//打印顺序表
void PrintList(SqList L){
printf("顺序表中元素依次为:");
for (int i = 0; i<L.length; i++)
{
printf("%d ", L.data[i]);
}
printf("\n");
}
//主函数
int main(){
SqList L;
InitList(L);
if(CreateList(L,5)){
PrintList(L);
printf("此时顺序表的长度为:%d\n",L.length);
}
ListInsert(L,3,3);
PrintList(L);
printf("此时顺序表的长度为:%d\n",L.length);
int e;
if (ListDelete(L,5,e))
{
printf("原顺序表被删除第5个元素后,");
PrintList(L);
printf("此时顺序表的长度为:%d\n",L.length);
}
printf("顺序表中第3个数字是:%d\n",GetElem(L,3));
printf("顺序表中值为5的数学位置在第%d个\n",LocateElem(L,5));
printf("此时顺序表的长度为:%d\n",L.length);
return 0;
}