顺序表:
线性表的顺序存储结构是一种随机存取的存储结构。顺序表存储结构容易实现随机存取线性表的第 i 个数据元素的操作,但在实现插入、删除的操作时要移动大量数据元素,所以,它适用于数据相对稳定的线性表,如职工工资表、学生学籍表等
顺序表插入,删除操作的时间复杂度
设pi是在第i个元素之前插入一个元素的概率,则在长度为n的线性表中插入一个元素时所需移动元素次数的平均次数为:
设qi是删除第i个元素的概率,则在长度为n的线性表中删除一个元素所需要移动元素次数的平均次数为:
=
假设在线性表中任意位置上插入和删除元素的概率都是相等的
由上可得:
若表长为n则删除和插入的时间复杂度为O(n)。
顺序表相关操作代码实现
下列代码中涉及到与顺序表相关的基本操作,包括:删除(包含了数组和指针两种实现),插入(包含了数组和指针两种实现),求前驱,求后继,翻转,排序,在尾部追加元素,初始化,销毁,置空等基本操作,还包括: 顺序表的无序和有序合并等拓展操作,以及相关的主函数测试。
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define LIST_INIT_SIZE 6 //要申请多少个数组元素空间
#define LIST_INCREMENT 2 //当存储空间已满时,需要增加的元素空间个数
typedef struct Array
{
int *base; //相当于数组元素首地址
int cnt; //数组元素的有效个数
int length; //数组元素的长度
}ARR,*PARR;
//基本操作
int Length(PARR pArr); //返回顺序线性表元素个数
void Init(PARR pArr); //线性表顺序存储的初始化
void Destroy(PARR pArr);//销毁顺序线性表
void Clear(PARR pArr); //置空顺序线性表
void Reverse(PARR pArr);//翻转
void Traverse(PARR pArr); //遍历数组
void Sort(PARR pArr); //排序
void append(PARR pArr,int e); //追加e元素到数组的尾部
bool Empty(PARR pArr); //判断顺序线性表是否为空
bool Get(PARR pArr,int i,int *e);//用e返回第i个数据元素的值
bool Prior(PARR pArr,int cur_e,int *pre_e);//用pre_e存储cur_e的前驱
bool Next(PARR pArr,int cur_e,int *next_e);//用next_e存储cur_e的后继
bool Insert(PARR pArr,int i,int e); //在第i个元素之前插入元素e
bool Delete(PARR pArr,int i,int *e);//删除第i个位置的元素,并用e存储删除的元素
//拓展操作
void Union(PARR La,PARR Lb);//将所有在线性表Lb中但不在La中的数据元素插入到La中
/*
已知线性表La和Lb中的数据元素按值非递减排列
归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
*/
void MergeList(PARR La,PARR Lb,PARR Lc);
int main()
{
ARR arr; //定义线性顺序表arr
int val;
Init(&arr); //初始化线性顺序表
append(&arr,1); //向线性顺序表中添加元素
append(&arr,8);
append(&arr,11);
append(&arr,6);
append(&arr,9);
append(&arr,4);
printf("测试追加函数,追加6个元素后:");
Traverse(&arr);
append(&arr,10);
append(&arr,7);
printf("测试追加函数,追加8个元素后:");
Traverse(&arr);
Sort(&arr);
printf("测试排序函数,排序后的元素为:");
Traverse(&arr);
if(Get(&arr,10,&val))
printf("测试Get函数,第四个元素为:%d\n",val);
else
printf("测试Get函数,您要返回的元素不存在!\n");
Reverse(&arr);
printf("测试翻转函数,翻转后的元素为:");
Traverse(&arr);
if(Insert(&arr,2,99))
printf("测试插入函数指针实现,插入成功!\n");
else
printf("测试插入函数指针实现,插入失败!");
Traverse(&arr);
// if(Insert(&arr,2,101))
// printf("测试插入函数数组实现,插入成功!\n");
// else
// printf("测试插入函数数组实现,插入失败!");
// Traverse(&arr);
//if(Delete(&arr,4,&val))
// printf("测试删除函数指针实现,您删除的元素是%d\n",val);
//else
// printf("测试删除函数指针实现,您删除的元素不存在!\n");
// Traverse(&arr);
if(Delete(&arr,0,&val))
printf("测试删除函数数组实现,您删除的元素是%d\n",val);
else
printf("测试删除函数数组实现,您删除的元素不存在!\n");
Traverse(&arr);
printf("测试Length函数,当前有效元素个数为%d\n",Length(&arr));
if(Prior(&arr,6,&val))
printf("测试前驱函数,6的前驱元素是%d\n",val);
else
printf("测试前驱函数,查询失败!\n");
if(Next(&arr,6,&val))
printf("测试后继函数,6的后继元素是%d\n",val);
else
printf("测试后继函数,查询失败!\n");
Clear(&arr);
Traverse(&arr);
if(Empty(&arr))
printf("测试是否为空, 空\n");
else
printf("测试是否为空, 非空\n");
Destroy(&arr);
printf("销毁顺序表!\n");
ARR La,Lb,Lc;
Init(&La);
Init(&Lb);
Init(&Lc);
append(&La,3);
append(&La,5);
append(&La,8);
append(&La,11);
append(&Lb,2);
append(&Lb,6);
append(&Lb,8);
append(&Lb,9);
append(&Lb,11);
append(&Lb,15);
append(&Lb,20);
/* printf("线性表La的元素为:");
Traverse(&La);
printf("线性表Lb的元素为:");
Traverse(&Lb);
Union(&La,&Lb);
printf("LaULb=");
Traverse(&La);
*/
MergeList(&La,&Lb,&Lc);
Traverse(&Lc);
return 0;
}
int Length(PARR pArr)
{
return pArr->cnt;
}
void Init(PARR pArr)
{
pArr->base=(int *)malloc(LIST_INIT_SIZE*sizeof(int));//申请大小为LIST_INIT_SIZE的数组元素空间
if(NULL==pArr->base)
exit(-1); //动态分配内存失败,退出程序
pArr->cnt=0; //初始有效元素个数为0
pArr->length=LIST_INCREMENT; //数组元素的长度为申请的长度
}
void Destroy(PARR pArr)
{
free(pArr->base);//释放base所指向的已经申请的元素的空间
pArr->base=NULL;//防止产生野指针,乱指向
pArr->cnt=0; //将有效元素个数和长度置为0
pArr->length=0;
}
void Clear(PARR pArr)
{
pArr->cnt=0; //将有效元素个数置为0,其他不变
}
void Reverse(PARR pArr)
{
int *p=pArr->base;
int *q=pArr->base+pArr->cnt-1;
int temp;
while(p<q)
{
temp=*p;
*p=*q;
*q=temp;
p++;
q--;
}
}
void Traverse(PARR pArr)
{
if(Empty(pArr))
{
printf("数组内容为空\n");
}
else
{
for(int i=0;i<pArr->cnt;i++)
{
printf("%d ",pArr->base[i]);
}
printf("\n");
}
}
void Sort(PARR pArr)
{
int i,j,temp;
for(i=0;i<pArr->cnt-1;i++)
{
for(j=i+1;j<pArr->cnt;j++)
{
if(pArr->base[i]>pArr->base[j])
{
temp=pArr->base[i];
pArr->base[i]=pArr->base[j];
pArr->base[j]=temp;
}
}
}
}
void append(PARR pArr,int e)
{
int *newbase=NULL;
if(pArr->cnt>=pArr->length) //当前存储空间已满,增加分配
{
newbase=(int *)realloc(pArr->base,(pArr->length+LIST_INCREMENT)*sizeof(int));
if(NULL==newbase)
{
printf("动态内存分配失败!\n");
exit(-1); //分配空间失败,退出程序
}
pArr->base=newbase; //新的数组元素首地址
pArr->length+=LIST_INCREMENT;
}
pArr->base[pArr->cnt]=e;
pArr->cnt++; //有效元素个数加一
}
bool Empty(PARR pArr)
{
if(pArr->cnt==0)
return true;
else
return false;
}
bool Get(PARR pArr,int i,int *e)
{
if(i<1||i>pArr->cnt)
return false;
*e=pArr->base[i-1]; //或者*e=*(pArr->base+i-1)
return true;
}
bool Prior(PARR pArr,int cur_e,int *pre_e)
{
//求前驱元素,用pre_e存储cur_e的前驱元素
int i=2;
int *p=pArr->base+1;
while(i<=pArr->cnt&&*p!=cur_e)
{
i++;
p++;
}
if(i>pArr->cnt)
return false;
*pre_e=*(p-1);
return true;
}
bool Next(PARR pArr,int cur_e,int *next_e)
{
//求后继元素,用next_e存储cur_e的后继元素
int i=1;
int *p=pArr->base;
while(i<pArr->cnt&&*p!=cur_e)
{
i++;
p++;
}
if(i==pArr->cnt)
return false;
*next_e=*(p+1);
return true;
}
bool Insert(PARR pArr,int i,int e)
{
int *newbase,*p,*q;
if(i<1||i>pArr->cnt+1) //判断i值是否合法
return false;
if(pArr->cnt>=pArr->length) //当前存储空间已满,增加分配
{
newbase=(int *)realloc(pArr->base,(pArr->length+LIST_INCREMENT)*sizeof(int));
if(NULL==newbase)
exit(-1); //分配空间失败,退出程序
pArr->base=newbase; //新的数组元素首地址
pArr->length+=LIST_INCREMENT;
}
p=pArr->base+i-1;
for(q=pArr->base+pArr->cnt-1;q>=p;q--)
*(q+1)=*q;
*p=e;
/*
//数组实现:
int k;
for(k=pArr->cnt-1;k>=i-1;k--)
{
pArr->base[k+1]=pArr->base[k];
}
pArr->base[i-1]=e;
*/
pArr->cnt++; //有效元素个数加一
return true;
}
bool Delete(PARR pArr,int i,int *e)
{
int *p,*q;
if(i<1||i>pArr->cnt) //判断i值是否合法
return false;
/*
p=pArr->base+i-1;
*e=*p;
for(q=pArr->base+pArr->cnt-1;p+1<=q;p++)
*p=*(p+1);
*/
//数组实现:
*e=pArr->base[i-1];
int k;
for(k=i-1;k<pArr->cnt-1;k++)
{
pArr->base[k]=pArr->base[k+1];
}
pArr->cnt--; //有效元素个数减一
}
void Union(PARR La,PARR Lb)
{
//将所有在线性表Lb中但不在La中的数据元素插入到La中
int i,j,val,flag;
for(i=1;i<=Lb->cnt;i++)
{
flag=0;
Get(Lb,i,&val);
for(j=0;j<La->cnt;j++)
{
if(val==La->base[j])
{
flag=1;
break;
}
}
if(flag==0)
{
append(La,val);
}
}
}
void MergeList(PARR La,PARR Lb,PARR Lc)
{
//已知线性表La和Lb中的数据元素按值非递减排列
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列
int i=1,j=1,va,vb;
while(i<=La->cnt&&j<=Lb->cnt)
{
Get(La,i,&va);
Get(Lb,j,&vb);
if(va<=vb)
{
append(Lc,va);
i++;
}
else
{
append(Lc,vb);
j++;
}
}
while(j<=Lb->cnt)
{
Get(Lb,j,&vb);
append(Lc,vb);
j++;
}
while(i<=La->cnt)
{
Get(La,i,&va);
append(Lc,va);
i++;
}
}