文章目录
前言
线性表的顺序存储结构,指的是用一段地址连续(物理位置相邻)的存储单元依次存储线性表的数据元素。
a1->a2->a3->……->ai-1->ai->……->an
顺序表的顺序结构,说白了,就是在内存中找了块地儿,通过占位的形式,把一定内存空间给占了,然后把相同的数据类型的数据元素依次存放在这块空地中,既然线性表的每一个元素都相同,所以可以用C语言(其他语言也相同)的一堆数组来实现顺序存储结构。
顺序存储代码
1.1 线性表的顺序存储的结构代码
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int ElemType; /* ElemType类型根据实际情况而定,这里为int */
typedef struct
{
ElemType data[MAXSIZE]; /* 数组,存储数据元素 */
int length; /* 线性表当前长度 */
}SqList;
这里我们就发现,顺序存储结构需要三个属性:
- 存储空间的起始位置,数组data,它的存储位置就是存储空间的存储位置。
- 线性表的最大存储容量:数组长度MAXSIZE。
- 线性表的当前长度:length。
用我们的C语言代码表示顺序表存储结构就可以写为
typedef struct Sqlist
{
int *elem;//元素
int length;//元素个数,即长度
}Sqlist;
1.2 数组长度与线性表长度的区别
数组长度:存放线性表的存储空间的长度,存储分配后这个量一般是不变的。
数组大小一定不可以改变吗?
一般高级语言,比如C、VB、C++都可以用编程手段实现动态分配数组,不过者会带来性能上的损耗。
线性表的长度:是线性表中数据元素的个数,随着线性表插入和删除操作的进行,这个量是变化的。
在任意时刻,线性表的长度应该小于等于数组的长度
1.3 地址计算方法
线性表当前长度length(a1到an) | || | |||||||
---|---|---|---|---|---|---|---|---|
下标 | 0 | 1 | i-2 | i-1 | n-1 | |||
a1 | a2 | ··· | ai-1 | ai | ··· | an | 空闲空间 | |
数组的长度MAXSIZE(a1到空闲空间) |
存储器中的每个存储单元都有自己的编号,这个编号称为地址。
假设每个数据元素占用的是c个存储单元,那么线性表中第i+1个数据元素的存储位置和第i个数据元素的存储位置满足下列关系(LOC表示获得存储位置的函数)。
LOC(ai+1)=LOC(ai)+c
所以对于第i个数据元素ai的存储位置可以由ai推算得出:
LOC(ai)=LOC(a1)+(i-1)* c
通过这个公式,可以随时算出线性表中任意位置的地址,不管他是第一个还是最后一个,都是相同的时间。那么我们对每个现行白哦位置的存入或者取出数据,对于计算机来说都是相等的时间,也就是一个常数,因此用我们算法中学到的时间复杂度的概念来说,它的存取时间性能为O(1)。我们通常把具有这一特点的存储结构称为随机存取结构
1.4 获得元素操作
#define LIST_MaxSize 1000 //该顺序表最大的数量
typedef int ElemType; //给int定义一个别名
typedef enum Status
{
success,fail,NoCreate //success表成功,fail表失败,NoCreate表顺序表还未创建
}Status;
Status status; //定义Status这个枚举变量,status是表明顺序表基本操作状态
/*
声明:typedef是定义一个别名,enum是枚举,typedef enum status的意思就是定义一个枚举类型,这个类型包含success,fail,NoCreate三种,在程序中表征状态。
*/
/*1、创建顺序表*/
Status List_Init(Sqlist *L)
{
int i;
L->elem=(ElemType *)malloc(LIST_MaxSize*sizeof(ElemType));//要开辟多余的空间是为了后面的插入
for (i=0;i<L->length;i++)
{
printf("请输入第%d个数值:",i+1);
scanf("%d",&L->elem[i]);
}
if(L->elem)
{
for (i=0;i<L->length;i++)
{
printf("%d\t",L->elem[i]);
}
return success;
}
return fail;
}
1.5 插入操作
插入算法思路:
- 如果插入位置不合理,抛出异常;
- 如果线性表长度大于等于数组长度,则抛出异常或动态增加容量;
- 从最后一个元素开始向前遍历到第i个位置,分别将他们都向后移一个位置;
- 将要插入元素填入位置i处;
- 表长加1。
/*2、插入一个数值*/
/*注意i是指位置,第1个位置是从数组的0开始的*/
Status List_Insert(Sqlist *L,ElemType elem,int pos)//第pos个元素换为elem
{
int i;
if (L->length==LIST_MaxSize)
return fail;
if (pos<1||pos>L->length)
{
printf("out of bound");
return fail;
}
if (i<=L->length)
{
for (i=L->length-1;i>=pos-1;i--)
{
L->elem[i+1]=L->elem[i];//数据元素后移一位
}
}
L->elem[pos-1]=elem;
L->length++;
return success;
}
1.6 删除操作
删除算法思路:
- 如果删除位置不合理,抛出异常;
- 去除删除元素;
- 从删除原宿位置开始遍历到最后一个元素位置,分别将它们都向前移动位置;
- 表长减1。
Status List_Remove(Sqlist *L,int pos)
{
int i;
for(i=pos-1;i<L->length-1;i++)
{
L->elem[i]=L->elem[i+1];
}
L->length--;
return success;
}
1.7 销毁链表
Status List_Destroy(Sqlist *L)
{
if(status==NoCreate)
{
printf("您还没有创建顺序表!请先创建顺序表\n");
}
else if(L->elem)
{
free(L->elem);//释放申请空间
L->elem=NULL;//置为空指针,保证使用安全
L->length=0;
return NoCreate;
}
}
1.8 求前驱算法
Status List_Prior(Sqlist *L,int pos)
{
ElemType elem;
if(pos>1&&pos<=L->length)
{
elem=L->elem[pos-1-1];
printf("前驱数值为:%d\n",elem);
return success;
}
return fail;
}
1.9 求后继算法
Status List_Next(Sqlist *L,int pos)
{
ElemType elem;
if (pos>1&&pos<=L->length-1)
{
elem=L->elem[pos-1];
printf("后继数值为:%d\n",elem);
return success;
}
return fail;
}
总结
主函数
int main()
{
printf("--------------------提示:该顺序表最大能存1000个元素--------------------\n\n");
int i;
int pos;
int count=0;
int n;
status=NoCreate;
Sqlist L;
L.length=0;//空表,此时还未创建顺序表
ElemType elem;
printf("*******************1、创建顺序表\t");
printf("2、按数值查找*******************\n");
printf("*******************3、按位置查找\t");
printf("4、插一个数值*******************\n");
printf("*******************5、删一个数据\t");
printf("6、销毁顺序表*******************\n");
printf("*******************7、求前驱算法\t");
printf("8、求后继算法*******************\n");
printf("*******************9、菜单的选项\t");
printf("10、展示顺序表*******************\n");
printf("*******************11、顺序表个数\t");
printf("12、结束该程序*******************\n");
while(1)
{
printf("请输入您想要运行的程序序号:");
scanf("%d",&n);
switch(n)
{
case 1:
{
printf("您想初始化这个顺序表多少个元素呢?(随机数):");
scanf("%d",&L.length);
if (L.length>LIST_MaxSize)
{
printf("元素个数超过了最大值!\n");
break;
}
status=List_Init(&L);
if (status==success)
{
printf("\n顺序表初始化成功!\n");
}
if (status==fail)
{
printf("\n顺序表初始化失败!\n");
}
break;
}
case 2:
{
if(status==NoCreate)
{
printf("您还没有创建顺序表!请先创建顺序表!\n");
}
else
{
printf("请输入你想要查找的数值:");
scanf("%d",&elem);
status=List_Locate(&L,elem,&pos,&count);
if(status==success)
{
printf("找到了!第一次出现在第%d个位置,共出现了%d次\n",pos+1,count);
}
else
{
printf("您输入的数值不在顺序表中!\n");
}
break;
}
}
case 3:
{
if (status==NoCreate)
{
printf("您还没有创建顺序表!请先创建顺序表!\n");
}
else
{
printf("按位置查找,您查找的数字需要为:");
scanf("%d",&pos);
status=List_Retrieve(&L,&elem,&pos);
if(status==success)
{
printf("该数值为:%d\n",elem);
}
else
{
printf("您输入的序号越界了!\n");
}
break;
}
}
case 4:
{
if(status==NoCreate)
{
printf("您还没有创建顺序表!请先创建顺序表\n");
}
else
{
printf("请输入您想插入的元素位置:");
scanf("%d",&pos);
if(pos>L.length||L.length==LIST_MaxSize)
{
printf("您插入的元素的位置超出了链表可接受范围!\n");
break;
}
printf("请输入您插入元素的数值:");
scanf("%d",&elem);
status=List_Insert(&L,elem,pos);
if (status==success)
printf("插入成功!\n");
else
printf("插入不成功!\n");
}
break;
}
case 5:
{
if (status==NoCreate)
printf("您还没有创建顺序表!请先创建顺序表\n");
else
{
printf("请输入您想删除的元素位置:");
scanf("%d",&pos);
if (pos>L.length||L.length==LIST_MaxSize)
{
printf("您删除的元素超出了您创建顺序表的范围");
break;
}
status=List_Remove(&L,pos);
if (status==success)
printf("删除成功!\n");
}
break;
}
case 6:
{
status=List_Destroy(&L);
if (status==NoCreate)
printf("销毁成功!\n");
status=NoCreate;
break;
}
case 7:
{
if (status==NoCreate)
printf("您还没有创建顺序表!请先创建顺序表\n");
else
{
printf("请输入元素位置:");
scanf("%d",&pos);
status=List_Prior(&L,pos);
if(status==fail)
printf("该位置没有前驱!\n");
}
break;
}
case 8:
{
if (status==NoCreate)
printf("您还没有创建顺序表!请先创建顺序表\n");
else
{
printf("请输入元素位置:");
scanf("%d",&pos);
status==List_Next(&L,pos);
if (status==fail)
printf("该位置没有后继!\n");
}
break;
}
case 9://长时间运行会找不到菜单所以可以为选项者提供选择
{
printf("---------------------------------------------------------------------\n");//分割线
printf("*******************1、创建顺序表\t");
printf("2、按数值查找*******************\n");
printf("*******************3、按位置查找\t");
printf("4、插一个数值*******************\n");
printf("*******************5、删一个数据\t");
printf("6、销毁顺序表*******************\n");
printf("*******************7、求前驱算法\t");
printf("8、求后继算法*******************\n");
printf("*******************9、菜单的选项\t");
printf("10、展示顺序表*******************\n");
printf("*******************11、顺序表个数\t");
printf("12、结束该程序*******************\n");
printf("---------------------------------------------------------------------\n");//分割线
}
case 10:
{
if (status==NoCreate)
printf("您还没有创建顺序表!请先创建顺序表\n");
else
{
printf("\n---------------------------------------------------------------------\n");//分割线
for (i=0;i<L.length;i++)
{
printf("%d\t",L.elem[i]);
}
printf("\n---------------------------------------------------------------------\n");//分割线
}
break;
}
case 11:
{
if(status==NoCreate)
printf("您还没有创建顺序表!请先创建顺序表\n");
else
printf("顺序表的元素个数为:%d\n",L.length);
break;
}
case 12:
{
printf("再见!");
return 0;
}
default:
{
printf("请输入1~12内的整数!\n");
break;
}
}
count=0;//用完一次重置
pos=0;//用完一次重置
}
}