线性表的顺序存储结构
顺序存储结构封装需要三个属性:
1.存储空间的起始位置,数组data,它的存储位置就是线性表存储空间的存储位置
2.线性表的最大存储容量,数组的长度MaxSize
3.线性表的当前长度:length
当前长度与数组长度区别:数组长度就是该顺序表的总长度,如果不进行扩容的话,就是不变的。而当前长度在数据的变化中,就会发生相应的变化。
PS:线性表是正常的读数方法,一下标1开始的。
存储时间性能:O(1)
性能:存取以及读取不管是在哪个位置,其时间复杂度都是O(1),而在插入还是删除其时间复杂度都是O(n)
结论:比较适合数据的存取而不适合经常性增删的情况。
顺序存储结构的优缺点
1.优点:
- 无须为表示表中元素之间的逻辑关系而增加额外的存储空间
- 可以快速的存取表中任意位置的元素。
2.缺点:
- 插入以及删除操作需要移动大量的元素。
- 当线性表长度变化较大时,难以确定存储空间的容量。
- 容易造成存储空间的碎片。
具体代码的实现:
// 头文件部分,进行常量参数初始化
#define LIST_INT_SIZE 10 //线性顺序表初始动态分配内存大小
#define INCREAMENT 2 //线性表扩容一次性增量
#define OK 1
#define ERROW -1
#define OVERFLOW -2
#include<stdio.h>
#include <stdlib.h>//malloc函数包含在其中
typedef int Elemtype; //线性表的数据类型
typedef int Status; // 状态数据类型
// 顺序表存储结构定义
typedef struct {
Elemtype *elem; //定义线性表内数据元素的数据类型
int length; //表当前长度
int listsize; //表当前空间容量大小
} SqList; //表名
// 初始化一个顺序表
Status InitList(SqList &L) {
L.elem = (Elemtype *)malloc(LIST_INT_SIZE * sizeof(Elemtype)) ;//动态分配内存,分配后可以将l.elem作为数组使用
if(!L.elem) { //对内存分配的结果判断
exit(OVERFLOW);
} //这个地方可以去查一下资料
// if(L.elem == NULL) {
// printf("分配内存失败")
// exit(1);
// }
//关于内存分配结果的判断,又该如何去进行判断
//这种方法进行判断又是否正确
L.length = 0; //对表长初始化归0
L.listsize = LIST_INT_SIZE;
return OK;
}
// 创建一个顺序表
Status CreateList(SqList &L) {
int i;
InitList(L);
printf("请输入元素个数:\n");
scanf("%d",&L.length);
printf("\n请输入您要输入的元素\n");
for(i=0; i<L.length; i++) {
scanf("%d",&L.elem[i]);
}
printf("顺序表已创建成功,打印表请选择功能 *3\n");
return OK;
}
// 顺序表的遍历
Status TraverseList(SqList &L) {
int i;
printf("表中元素为:\n");
for(i=0; i<L.length; i++)
printf("%d ",L.elem[i]);
printf("\n\n顺序表输出完毕!\n");
}
//顺序表的插入
// 表L 位置 i Elemtype 要插入的元素
Status InsertList(SqList &L,int i,Elemtype e) {
int* newbase;
int j;
if(i < 1 ||i > L.length+1) { // 判断所要插入的位置
return ERROW;
}
if(L.length>=L.listsize) {
newbase = (Elemtype*)realloc(L.elem,(L.listsize+INCREAMENT)*sizeof(Elemtype));
if(!newbase) {
exit(OVERFLOW);
}
L.elem = newbase;
L.listsize += INCREAMENT;
}
for(j = L.length-1; j>i-1; j--) {
L.elem[j+1]=L.elem[j];
}
L.elem[i-1] = e;
L.length++;
return OK;
}
//删除指定位置元素并返回出来
Status deleteListElem(SqList &L,int i) {
Elemtype e;
int j;
if(i<1 || i>L.length) {
return ERROW;
}
e = L.elem[i-1];
for(j = i-1 ; j<=L.length; j++) {
L.elem[j] = L.elem[j+1];
}
L.length--;
return e;
}
//判断一个值是不是线性表中的元素并返回第几个元素
Status ifElemExit(SqList &L,Elemtype e) {
int i = 0;
for(; i<L.length; i++) {
if(e==L.elem[i])
break;
}
if(i>=L.length) {
return ERROW;
} else {
return i;
}
}
//输出一个位置的数据元素
Status GetElem(SqList &L,int i) {
if(i<1||i>L.length) {
return ERROW;
}
return L.elem[i-1];
}
//根据元素的值来进行删除
Status deleteElemByR(SqList &L,Elemtype e) {
int i = 0;
i = ifElemExit(L,e);
if(i==-1) {
printf("该值不再线性表中:");
return ERROW;
} else {
deleteListElem(L,i+1);
printf("删除成功!删除的是位置为%d,值为%d",i,e);
return OK;
}
}
//将线性表进行递减排序操作
Status SortByMao(SqList &L) {
Elemtype e;
for(int j=0; j<L.length; j++) {
for(int i=0; i<L.length-i-j; i++) {
if(L.elem[i]<L.elem[i+1]) {
e = L.elem[i];
L.elem[i] = L.elem[i+1];
L.elem[i+1]=e;
}
}
}
}
void UnionTwo(SqList &la,SqList &lb) {
int la_length = la.length;
int lb_length = lb.length;
for(int i=1;i<=lb.length;i++){
Elemtype e= GetElem(Lb,i);
if(ifElemExit(La,e)==-1){
InsertList(La,la_length,e);
la_length++;
la.length++;
}
}
}
/***主提示输出函数***/
void printlin() {
printf("\n");
printf("\t\t\t线性顺序表基本操作学习系统\n");
printf("\t\t\t ***主菜单***\n\n");
printf("\t\t\t *1 创建一个顺序表\n");
printf("\t\t\t *2 定位输出一个数据元素\n");
printf("\t\t\t *3 输出顺序表中所有元素\n");
printf("\t\t\t *4 定位插入一个数据元素\n");
printf("\t\t\t *5 定位删除一个数据元素\n");
printf("\t\t\t *6 定值删除一个数据元素\n");
printf("\t\t\t *7 清空顺序表\n");
printf("\t\t\t *8 销毁顺序表\n");
printf("\t\t\t *9 对表内数据元素进行非递减排序\n");
printf("\t\t\t *0 结束程序\n");
}
//清空线性表
void clearList(SqList &L) {
if(L.length!=0) {
L.length = 0; //由于顺序表的用得是与数组一样的内存空间,
//所以标的清空只要将表长归零即可,由此可见,表长是线性表非常重要的部分
}
}
//销毁线性表
void destoryList(SqList &L) {
if(L.length!=0) {
free(L.elem);
L.elem = NULL;//使用free后就需要对元素进行赋空操作
}
}
int main() {
int i,j,k;
Elemtype e;
SqList L;
L.length=0;
printf("编写此程序目的是自我学习线性表顺序表\n");
printlin();
while(1) {
int t;
scanf("%d",&t);
if(t!=0)
if(t==1||L.length!=0) {
switch(t) {
case 1:
if(L.length!=0) {
printf("顺序表已存在,是否重新创建顺序表?\n");
printf("*1 是 *2 否\n");
scanf("%d",&i);
if(i==1)
CreateList(L);
} else
CreateList(L);
break;
case 0:
break;
case 3:
TraverseList(L);
break;
case 7:
clearList(L);
printf("清空完毕,返回主菜单\n\n");
break;
case 4:
printf("输入要插入的位置\n");
scanf("%d",&i);
printf("请输入要插入的数据\n");
scanf("%d",&j);
k=InsertList(L,i,j);
if(k==-1) {
printf("插入位置不合法,插入数据操作失败!\n\n");
} else
printf("插入数据成功\n\n");
break;
case 5:
printf("请输入要删除数据位置\n");
scanf("%d",&i);
e = deleteListElem(L,i);
printf("删除掉的元素是第%d个位置,它的值是%d",i,e);
break;
case 2:
printf("请输入要需要得到数据位置:");
scanf("%d",&i);
e = GetElem(L,i);
printf("第%d个位置上的元素值为:%d",i,e);
break;
case 6:
printf("请输入需要删除的值:");
scanf("%d",&e);
deleteElemByR(L,e);
break;
case 8:
destoryList(L);
printf("销毁成功!");
break;
case 9:
SortByMao(L);
break;
default: {
printf("输入有误,可以重新选择,退出按0!\n");
}
}
} else
printf("顺序表未创建或已清空或销毁,请先创建顺序表\n");
system("pause");
system("CLS");
printlin();
if(t==0)
break;
}
return 0;
}