单链表-顺序存储
本文参考自《大话数据结构》,有兴趣的读者可以自行阅读。
顺序存储结构
#define MAXSIZE 20 //存储空间初始分配量
typedef int ElemType; //ElemType类型根据实际情况而定,这里假设为int
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素,最大值为MAXSIZE
int length; //线性表当前长度
}SqList;
对于第i个数据元素ai的存储位置可以由a1推算得出:
*LOC(ai)=LOC(a1)+(i-1)c;
通过这个公式可以随时算出线性表中任意位置的地址,不管是第一个还是最后一个,都是相同的时间。那么我们对每个线性表位置的存入或者取出数据,对于计算机来说都是相等的时间,也就是一个常数,因此用我们算法中学到的时间复杂度的概念来说,它的存取时间性能为O(1)。我们通常把具有这一特点的存储结构成为随机存取结构。
获得元素操作
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
/* 初始条件:顺序线性表L已存在,1<=ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
Status GetElem(SqList L,int i,ElemType *e)
{
if(L.length == 0 || i<1 ||L.length)
return ERROR;
*e = L.data[i-1];
return OK;
}
插入操作
思路:
- 如果插入位置不合理,抛出异常;
- 如果线性表长度大于等于数组长度,则抛出异常或动态增加容量;
- 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;
- 将要插入元素填入位置i处;
- 表长加1;
/* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if(L->length == MAXSIZE) //顺序线性表已经满
return ERROR;
if(i<1 || i>L->length+1) //当i不在范围内时
return ERROR;
if(i<=L->length) //若插入数据位置不在表尾
{
for(k = L->length-1; k>= i-1; k--) //将要插入位置后数据元素向后移动一位
L->data[k+1] = L->data[k];
}
L->data[i-1] = e; //将新元素插入
L->length++;
return OK;
}
删除操作
思路:
- 如果删除位置不合理,抛出异常;
- 取出删除元素;
- 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
- 表长减1;
/* 初始条件:顺序线性表L已存在,1<=i<=ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(SqList *L, int i, ElemType *e)
{
int k;
if(L->length == 0) //线性表位空
return ERROR;
if(i<1 || i>L->length) //删除位置不正确
return ERROR;
*e = L->data[i-1];
if(i<L->length) //如果删除不是最后位置
{
for(k=i;k<L->length;k++) //将删除位置后继元素前移
L->data[k-1] = L->data[k];
}
L->length--;
return OK;
}
优点
- 无须为表示表中元素之间的逻辑关系而增加额外的存储空间;
- 可以快速地存取表中任一位置的元素;
缺点
- 插入和删除操作需要移动大量元素;
- 当线性表长度变化较大时,难以确定存储存储空间的容量;
- 造成存储空间的"碎片";
代码实现
#include <stdio.h>
#define MAXSIZE 20 //存储空间初始分配量
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int ElemType; //ElemType类型根据实际情况而定,这里假设为int
//结构体---单链表顺序存储
typedef struct
{
ElemType data[MAXSIZE]; //数组存储数据元素,最大值为MAXSIZE
int length; //线性表当前长度
}SqList;
//指针方式获取元素
//Status getElem(SqList* list, int i, ElemType* e){
// if(i <= 0){
// printf("索引值小于0,不存在该数据\n");
// return ERROR;
// }else if(i > list->length){
// printf("索引值超出边界\n");
// return ERROR;
// }else{
// *e = list->data[i-1];
// printf("*e:%d\n",*e);
// return TRUE;
// }
//}
//获取元素
Status getElem(SqList list, int i, ElemType* e){
if(i <= 0){
printf("索引值小于1,不存在该数据\n");
return ERROR;
}else if(i > list.length){
printf("索引值超出边界\n");
return ERROR;
}else{
*e = list.data[i-1];
return TRUE;
}
}
//插入
Status insertElem(SqList* list, int i, ElemType e){
int j;
if(i<=0){
printf("插入的位置小于1,非法插入!\n");
return ERROR;
}else if(i>list->length+1){
printf("插入的位置大于链表长度,非法插入\n");
return ERROR;
}else{
// list->length++;
for(j=list->length-1;j>=i-1;j--){
list->data[j+1] = list->data[j];
}
list->data[i-1] = e;
list->length++;
printf("当前list长度:%d\n",list->length);
return TRUE;
}
}
//删除
Status deleteElem(SqList* list, int i){
int j;
if(i<1){
printf("索引值小于1,非法删除!\n");
return ERROR;
}else if(i>list->length){
printf("索引值超过链表长度,非法删除!\n");
return ERROR;
}else{
for(j=i-1;j<list->length;j++){
list->data[j] = list->data[j+1];
}
list->length--;
return TRUE;
}
}
//主函数
int main(){
Status continueFlag = TRUE; //是否继续循环菜单,默认循环
int i; //索引
int initNum; //初始化数值数
int insertNum, insertSize; //插入的数字和插入的位置
int deleteSize; //删除的数的位置
int inputNum; //查找第几个
int functionNum; //功能号
ElemType init = 1; //指针初始化
ElemType* e = &init;
//需初始化,不然会出错
// ElemType* e;
SqList sqList;
//指针
SqList* list = &sqList;
printf("输入要初始化的整型值的个数(不超过20个):\n");
scanf("%d",&initNum);
printf("输入%d个整型数字(不超过20个,空格分隔):\n",initNum);
for(i=0;i<initNum;i++){
scanf("%d", &sqList.data[i]);
}
sqList.length = initNum;
for(i=0;i<sqList.length;i++) //初始化检测
printf("链表的第%d个数据是:%d\n",i+1,sqList.data[i]);
printf("初始化完成!\n");
while(continueFlag){
printf("-----------菜单----------\n");
printf("----------1.查找--------\n");
printf("----------2.插入--------\n");
printf("----------3.删除--------\n");
printf("----------4.退出--------\n");
printf("请输入功能号:\n");
scanf("%d", &functionNum);
switch(functionNum){
case 1:
printf("------------查找-----------\n");
printf("输入数据在链表中的位置:\n");
//输入一个数
scanf("%d", &inputNum);
//查找
if(getElem(sqList, inputNum, e) == TRUE)
printf("第%d个元素的值为:%d\n",inputNum,*e);
break;
case 2:
//插入
printf("------------插入-----------\n");
printf("输入要插入的位置和数(空格分隔):\n");
scanf("%d %d",&insertSize, &insertNum);
if(insertElem(list, insertSize, insertNum) == TRUE){
printf("插入成功!第%d个数是%d.\n",insertSize,sqList.data[insertSize-1]);
for(i=0;i<sqList.length;i++)
printf("链表的第%d个数据是:%d\n",i+1,sqList.data[i]);
}
break;
case 3:
//删除
printf("------------删除-----------\n");
printf("输入要删除的位置:\n");
scanf("%d",&deleteSize);
if(deleteElem(list, deleteSize) == TRUE){
printf("删除成功!\n");
for(i=0;i<sqList.length;i++){
printf("链表的第%d个数据是:%d\n",i+1,sqList.data[i]);
}
}
break;
case 4:
continueFlag = FALSE;
printf("感谢使用!");
break;
default:
printf("功能号不存在,请重新输入!\n");
break;
}
}
return 0;
}
运行结果