线性表
相同类型+有限+序列
表长、空表、位序、表头表尾元素、直接前驱后继
初始化
InitList
销毁
DestroyList
插入
ListInsert
删除
ListDelete
按值查找
LocationElem
按位查找
GetElem
表长
Length
输出
Print
判空
Empty
自己定义操作
⭐为什么要实现数据结构基本操作?
1、团队合作编程,定义数据结构让别人能够很方便的使用(封装)
2、将常用的操作/运算封装成函数,避免重复工作,降低出错风险
顺序表
1、顺序表――用顺序存储的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
2.1、静态数组分配
#define MaxSize 10 //定义最大长度
typedef struct{
ElemType data [MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(静态分配方式
#include<stdio.h>
#define MaxSize 10 //定义静态数组的最大长度
typedef struct {
int data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
L.length = 0; //顺序表的初始长度为0
}
int main(){
SqList L;
InitList(L);
for(int i=0;i<MaxSize;i++){
printf("data[%d] = %d\n",i,L.data[i];
return 0;
}
静态分配的局限性:
1、数组满了也不能够重新改变数组长度或者加新的值。
2、申请的空间太多造成资源浪费。
2.2、动态分配
#define InitSize 10 //顺序表的初始长度
typedef struct{
ElemType *data; //指示动态数组分配的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(动态分配方式)
⭐⭐⭐malloc、free
#include<stdlib.h>
#define InitSize 10 //默认的最大长度
typedef struct{
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList;
void InitList(SeqList &L){
L.data = (int*)malloc(InitSize * sizeof(int));
L.length = 0;
L.MaxSize = InitSize;
}
//增加动态数组的长度
void IncreaseSize(SeqList &L,int len){
int *p = L.data;
L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
for(int i=0;i<L.length;i++){
L.data[i] = p[i]; //将数据复制到新的区域
}
L.MaxSize = L.Maxsize + len; //顺序表最大长度增加len
free(p); //释放掉原来的内存
}
int main(){
SeqList L;
InitList(L);
//往顺序表中随便插入几个元素
Increase(L,5);
return 0;
}
特性:
3.1、线性表插入
#define MaxSize 10 //定义最大长度
typedef struct{
ElemType data [MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表的当前长度
}SqList;
bool ListInsert(SqList &L,int i,int e){
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length >= MaxSize) //当前已存满,不能插入
return false;
for(int j=L.lemgth;j>=i;j--){ //将第i个元素及之后的元素后移
L.data[j] = L.data[j-1];
L.data[i-1] = e; //在位置i放入e
L.length++; //长度加1
return true;
}
int main(){
SqList L;
InitList(L);
//……省略一些代码,插入几个元素
ListInsert(L,3,3);
return 0;
}
时间复杂度
3.2、线性表删除
#define MaxSize 10 //定义最大长度
typedef struct{
ElemType data [MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表的当前长度
}SqList;
bool ListDelete(SqList &L,int i,int &e){
if(i<1||i>L.elngth){
return false;
}
e = L.data[i-1]; //被删除的元素赋值给e
for(int j = i;j<L.length;j++){
L.data[j-1] = L.data[j]; //将第i个位置的元素前移
L.length--;
}
return true;
}
int main(){
SqList L;
InitList(L);
//……省略一些代码,插入几个元素
int e = -1;
if(ListDelete(L,3,e)){
printf("已删除第3个元素,删除元素的值为%d\n",e);
}else{
printf("位序i不合法,删除失败\n");
}
return 0;
}
时间复杂度
4.1 按位查找
GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。
//静态分配:
#define MaxSize 10 //定义最大长度
typedef struct{
ElemType data[MaxSize]; //用静态的“数组”存放数据元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(静态分配方式)
ElemType GetElem(SqList L, int i){
return L.data[i-1];
}
//动态分配:
#define InitSize 10 //顺序表的初始长度
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
} SeqList; //顺序表的类型定义(动态分配方式)
ElemType GetElem(SeqList L, int i){
return L.data[i-1];
}
时间复杂度:O(1)
4.2 按值查找
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素。
#define InitSize 10 //顺序表的初始长度
typedef struct{
ElemType *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
} SeqList; //顺序表的类型定义(动态分配方式)
//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
int LocateElem(SeqList L,ElemType e){
for(int i=0;i<L.length;i++){
if(L.data[i]==e){
return i+1; //数组下标为i的元素值等于e,返回其位序i+1
}
}
return 0; //退出循环,说明查找失败
}
时间复杂度: