2.2线性表的顺序表示
2.2.1.0 顺序表的定义
知识总览
顺序表的定义
顺序表――用顺序存储的方式实现线性表顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
顺序表的实现——静态分配
静态顺序表
#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;
}
顺序表的实现——动态分配
动态顺序表
#include<stdio.h>
#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;
free(p);
}
int main(){
SeqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//插入元素
IncreaseSize(L,5);
return 0;
}
顺序表的特点:
1随机访问,即可以在 O(1}时间内找到第i个元素。
2存储密度高,每个节点只存储数据元素
3拓展容量不方便(即便采用动态分配的方式实现,拓展长度的时间复杂度也比较高)
4插入、删除操作不方便,需要移动大量元素
总结
2.2.2.1顺序表的插入删除
知识总览
顺序表的基本操作————插入
顺序表的插入
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 10
typedef struct{
int data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
L.length=0; //顺序表初始长度为0
}
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.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
//插入jige 元素
if(ListInsert(L,1,3)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
return 0;
}
插入操作的时间复杂度
最好情况:最好情况:新元素插入到表尾,不需要移动元素,i= n+1;循环o次;最好时间复杂度=o(1);
最坏情况:新元素插入到表头,需要将原有的n个元素全都向后移动,i = 1,循环n次;最坏时间复杂度= O(n);
平均情况:假设新元素插入到任何一个位置的概率相同,即 i=1,2,3,... , length+1的概率都是 ,i=1,循环n次; i=2时,循环n-1次; i=3,循环n-2次....... i =n+1时,循环0次,平均循环次数=
平均时间复杂度= O(n)
顺序表的基本操作——删除
顺序表的删除
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 10
typedef struct{
int data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
L.length=0; //顺序表初始长度为0
}
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.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
bool ListDelete(SqList &L,int i, int &e){
if(i<1||i>L.length) //判断i的范围是否有效
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;
}
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
if(ListInsert(L,1,3)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
int e=-1;
if(ListDelete(L,1,e))
printf("已删除第1个元素,删除的元素值为%d\n",e);
else
printf("位序i不合法,删除失败\n");
return 0;
}
删除操作的时间复杂度
最好情况:删除表尾元素,不需要移动元素,i= n+1;循环o次;最好时间复杂度=o(1);
最坏情况:删除表头元素,需要将后续的n-1个元素全都向前移动,i = 1,循环n次;最坏时间复杂度= O(n);
平均情况:假设删除任何一个元素的概率相同,即 i=1,2,3,... , length+1的概率都是 ,i=1,循环n次; i=2时,循环n-1次; i=3,循环n-2次....... i =n+1时,循环0次,平均循环次数=
平均时间复杂度= O(n)
总结
2.2.2.2 顺序表的查找
知识总览
顺序表的按位查找
按位查找(静态分配)
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 10
typedef struct{
int data[MaxSize];
int length;
}SqList;
void InitList(SqList &L){
L.length=0; //顺序表初始长度为0
}
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.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
int GetElem(SqList L,int i){
return L.data[i-1];
}
int main(){
SqList L; //声明一个顺序表
InitList(L); //初始化顺序表
if(ListInsert(L,1,3)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
printf("找到了%d",GetElem(L,1));
return 0;
}
按位查找(动态分配)
#include<stdio.h>
#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;
free(p);
}
bool ListInsert(SeqList &L,int i,int e){
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length>=L.MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
int GetElem(SeqList L,int i){
return L.data[i-1];
}
int main(){
SeqList L; //声明一个顺序表
InitList(L); //初始化顺序表
if(ListInsert(L,1,3)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
IncreaseSize(L,1);
printf("找到了%d",GetElem(L,1));
return 0;
}
按位查找的时间复杂度
时间复杂度:O(1)
顺序表的按值查找
按值查找(返回位序)
#include<stdio.h>
#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;
free(p);
}
bool ListInsert(SeqList &L,int i,int e){
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length>=L.MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--)
L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;
}
//在顺序表L中查找第一个元素值等于e的元素,并返回其位序
int LocateElem(SeqList L,int e){
for(int i=0;i<L.length;i++)
if(L.data[i]==e)
return i+1;
return 0;
}
int main(){
SeqList L; //声明一个顺序表
InitList(L); //初始化顺序表
if(ListInsert(L,1,3)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
if(ListInsert(L,2,8)==false){
printf("插入失败,插入范围无效或存储空间已满");
}
IncreaseSize(L,1);
printf("位序是%d",LocateElem(L,8));
return 0;
}
结构类型的比较
不能直接用==, 而是结构体内各元素逐个比较
按值查找的时间复杂度
总结
本文来自博客园,作者:hellowworld!,转载请注明原文链接:https://www.cnblogs.com/zhangsai/p/17768235.html
posted on 2023-10-16 20:11 hellowworld! 阅读(285) 评论(0) 编辑 收藏 举报