@[TOC](顺序表的建立及操作)
关于引用传递的说明
(1)传递引用给函数与传递指针的效果是一 样的,形参变化实参也发生变化。
(2)引用类型作形参,在内存中并没有产生实参的副本,它直接对实参操作;而一般变量作参数,形参与实参就占用不同的存储单元,所以形参变量的值是实参变量的副本。
因此,当参数传递的数据量较大时,用引用比用一般变量传递参数的时间和空间效率都好。
#include<stdio.h>
#include<stdlib.h>
#define ERROR 0
#define OK 1
#define MAXSIZE 100//表的最大长度
typedef int Status;//Status是函数的类型,其值是函数结果状态的代码
typedef int ElemType;
typedef struct
{
ElemType *elem;//定义一个数组
int length;//当前线性表的长度
}Sqlist;//定义一个Sqlist的类型的顺序表
Sqlist L;
Status InitList(Sqlist &L)//初始化一个空的线性表
{
L.elem=(ElemType *)malloc(sizeof(ElemType)*MAXSIZE);//给数组分配空间
if(L.elem)return OK;
if(!L.elem)return ERROR;//当分配空间失败时,会返回NULL指针
}
//线性表的取值
int GetElem(Sqlist L,int i,ElemType &e)//ElemType &e为引用类型做形参
{
if(i<1||i>L.length)
return ERROR;
e=L.elem[i-1];
return OK;
}
//判断线性表是否为空
int IsEmpty(Sqlist L)
{
if(L.length==0)
return OK;
}
int GetLength(Sqlist L)//获取线性表的长度
{
return(L.length);
}
//销毁线性表
int DestroyList(Sqlist &L)
{
if(L.elem)delete L.elem;
return OK;
}
//清空线性表
int ClearList(Sqlist &L)
{
L.length=0;
return OK;
}
//线性表的查找
Status LocateList(Sqlist &L,ElemType e)
{
int i;
for(i=0;i<L.length;i++)//从表头开始查找
{
if(L.elem[i]==e)
return i+1;//查找成功,将元素的位置返回
}
return ERROR;//查找失败,返回0
}
Status InsertList(Sqlist &L,int i,ElemType e)//顺序表的插入
{
if(i<1||i>L.length+1)//判断插入的位置是否合理
return ERROR;
if(L.length==MAXSIZE)//判断表长是否溢出
return ERROR;
for(int j=L.length-1;j>=i-1;j--)
{
L.elem[j+1]=L.elem[j];//将第i个位置的元素及之后的元素往后移
}
L.elem[i-1]=e;//将要插入的元素插在第i个位置
L.length++;//表长加一
return OK;
}
//线性表的删除
int DeleteList(Sqlist &L,int i,ElemType &e)
{
if(i<1||i>L.length)//判断删除的位置是否合理
return ERROR;
for(int j=i;j<=L.length;j++)
{
L.elem[j-1]=L.elem[j];//将第i个元素之后的元素往前移动
}
e=L.elem[i-1];
L.length--;//表长减一
return e;//将删除的元素返回
}
//主函数测试
int main()
{
if(InitList(L))//测试InitList函数
{
ElemType e;
printf("Init success!\n");
int i;
for(i=0;i<10;i++)
{
InsertList(L,i+1,i);//测试InsertList函数
}
printf("Length is %d\n",GetLength(L));//测试GetLength函数
if(GetElem(L,1,e))//测试GetElem函数
printf("The first element is %d\n",e);
else
printf("Element is not exist\n");
if(LocateList(L,2))//测试LocateList函数
printf("The element is located at %d\n",LocateList(L,2));
if(!LocateList(L,2))
printf("The element is not in this List\n");
if(DeleteList(L,3,e))//测试DeleteList函数
printf("The delete element is %d\n",e);
if(IsEmpty(L))//测试IsEmpty函数
printf("List is empty\n");
else
printf("List is not empty\n");
if(DestroyList(L))//测试DestroyList函数
{
printf("destroy_seccess\n");
}
if(ClearList(L))//测试ClearList函数
{
printf("ClearList success\n");
}
}
return 0;
}
关于用顺序表有关操作的平均空间复杂度,平均时间复杂度的计算
- 顺序表的查找
对含有n个记录的表,查找成功时:
ASL(Average Search Length)=1/n(1+2+3+…+n)=(n+1)/2
- 顺序表的插入
对含有n个记录的表
若插入在尾结点之后,则根本无需移动(特别快) ;
若插入在首结点之前,则表中元素全部后移(特别慢) ;
若要考虑在各种位置插入(共n+1)种可能
平均移动次数为:1/(n+1)*(n+n-1+…+1+0)=n/2;
- 顺序表的删除
若删除尾结点,则根本无需移动(特别快) ;
若删除首结点,则表中n-1个元素全部前移(特别慢) ;
若要考虑在各种位置删除(共n种可能)的平均移动次数
平均移动次数为:1/n(n-1+n-2+…+1+0)=(n-1)/2;
顺序表查找、删除、插入平均时间复杂度,空间复杂度的小结:
平均时间复杂度:
查找、插入、删除算法的平均时间复杂度为O(n);
平均空间复杂度:
.显然,顺序表操作算法的空间复杂度S(n)=O(1);
(没有占用辅助空间)
顺序表的优缺点
优点:
存储密度大(结点本身所占存储量/结点结构所占存储量);
可以随机存取表中任一元素;
缺点:
在插入、删除某一元素时,需要移动大量元素;
浪费存储空间;
属于静态存储形式,数据元素的个数不能自由扩充