(新人小白初学数据结构,(为了快速了解相关知识)在此对线性表的顺序存储结构相关知识做出整合,总结,同时参照了很多的资料,视频,博客等,如有雷同,emmm...... ,希望能够多多支持!!!)
一.线性表的的介绍。
线性表的定义
线性表(List):零个或多个数据元素的有限序列。线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素,除了最后一个元素an外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系。
在较复杂的线性表中,一个数据元素可以由若干个数据项组成。在这种情况下,常把数据元素称为记录,含有大量记录的线性表又称为文件
原文链接:https://blog.csdn.net/Real_Fool_/article/details/113463997
二.线性表的顺序存储结构。
线性表的顺序存储结构称为顺序表
,其基本思想是用一段地址连续的存储单元一次存储线性表的数据元素。
一.顺序表的空间分配。
顺序表中分配空间有静态和动态两种,静态分配的空间程序运行后无法再修改,增添,而动态分配则可以进行改变。
顺序表的静态分配和初始化。
typedef struct{
int data[MAXSIZE]; //静态内存分配
int length;
}Sqlist;
void Initlist (Sqlist *L)
{
L->length=0;
return TRUE;
}
顺序表的动态分配和初始化。
#define Max 10
//定义线性表数据类型
typedef struct{
int *data;
int length;
int Max_size;
}Sqlist;//把该数据类型命名为Sqlist
//线性表的初始化
void InitList(Sqlist &L){
L.data=(int*)malloc(sizeof(int)*Max); //动态内存分配
L.length=0;
L.Max_size=Max;
if(L.data!=0)
return TRUE;
else
return FALSE;
}
二.顺序表的基本操作。
这里都是一些构建顺序表需要用到的一些基本操作,我在此做出模块花总结,可能会缺少一些比较重要的操作,在此不一一列举。(总结前人智慧)
1.初始化
/* 初始化顺序线性表 */
Status InitList(SqList *L)
{
L->length=0;
return OK;
}
2.判断空表
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(SqList L)
{
if(L.length==0)
return TRUE;
else
return FALSE;
}
3.清空顺序表
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Status ClearList(SqList *L)
{
L->length=0;
return OK;
}
4.返回表中元素个数
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(SqList L)
{
return L.length;
}
5. 查找位置元素
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
Status GetElem(SqList L,int i,ElemType *e)
{
if(L.length==0 || i<1 || i>L.length)
return ERROR;
*e=L.data[i-1];
return OK;
}
6.查找元素位置
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int LocateElem(SqList L,ElemType e)
{
int i;
if (L.length==0)
return 0;
for(i=0;i<L.length;i++)
{
if (L.data[i]==e)
break;
}
if(i>=L.length)
return 0;
return i+1;
}
7.插入元素
/* 初始条件:顺序线性表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;
}
8.删除元素
/* 初始条件:顺序线性表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;
}
9.输出顺序表
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(SqList L)
{
int i;
for(i=0;i<L.length;i++)
visit(L.data[i]);
printf("\n");
return OK;
}
三.顺序表的优缺点。
优点:
- 无需为表示表中元素之间的逻辑关系而增加额外的储存空间
- 可以快速地存取表中任一位置的元素
缺点:
- 插入和删除操作需要大量元素
- 当线性表长度变化比较大时,难以确定储存空间的容量
- 造成储存空间的“碎片”
三.顺序表的使用(模拟顺序表)。
如果在刚才的顺序表的基本操作板块中没有弄明白,在这里可能会更加容易理解些。因为,为了保证执行程序时的可操作性,我在整合了操作步骤,并加上了大量提示语句(printf语句),可以让程序更容易理解。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
//预先处理
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
//构建线性表
typedef struct{
int data[MAXSIZE];
int length;
}Sqlist;
/* 初始化顺序线性表 */
void Initlist (Sqlist *L)
{
L->length=0;
printf("初始化成功!\n");
}
/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
bool ListEmpty(Sqlist L)
{
if(L.length==0)
{
printf("该表为空表!\n");
return TRUE;
}
else
{
printf("该表不为空表!\n");
return FALSE;
}
}
/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
bool ClearList(Sqlist *L)
{
L->length=0;
printf("顺序表已清空!\n");
return OK;
}
/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
bool Listlength(Sqlist L)
{
printf("顺序表的长度为:%d\n",L.length);
return L.length;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
bool GetElem(Sqlist L)
{
int i;
printf("请输入你要查询的元素所在位置:\n");
scanf("%d",&i);
if(L.length==0){
printf("当前线性表为空\n");
return FALSE;
}
if(i>L.length){
printf("超出当前元素个数!\n");
return FALSE;
}
printf("线性表第%d个元素为:%d\n",i,L.data[i-1]);
return TRUE;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
bool locateElem(Sqlist L)
{
int e,i;
printf("要查找的数据为:");
scanf("%d",&e);
if(L.length==0)
{
printf("当前顺序表为空!\n");
return ERROR;
}
for(i=0;i<L.length;i++)
{
if(L.data[i]==e)
{
printf("第1个与%d满足关系的数据元素的位序为:%d",e,L.data[i]);
break;
}
}
if(i>=L.length)
{
printf("没有找到该数据元素!\n");
return ERROR;
}
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
bool Listinsert(Sqlist *L)
{
int i,e;
printf("请输入要插入的位置和数据:");
scanf("%d %d",&i,&e);
if(L->length==MAXSIZE)
{
printf("顺序表已满!\n");
return ERROR;
}
if(i<1||i>L->length+1)
{
printf("插入的位置错误!");
return ERROR;
}
if(i<=L->length)
{
for(int k=L->length-1;k>=i-1;k--)
L->data[k+1]=L->data[k];
}
L->data[i-1]=e;
L->length++;
return OK;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
bool ListDelete(Sqlist *L)
{
int i;
printf("请输入要删除数据的位置:");
scanf("%d",&i);
if(L->length==0)
{
printf("顺序表已空!\n");
return ERROR;
}
if(i<1||i>L->length)
{
printf("删除的位置错误!");
return ERROR;
}
if(i<L->length)
{
for(int k=i;k<L->length;k++)
L->data[k-1]=L->data[k];
}
L->length--;
return OK;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
bool ListTraverse(Sqlist L)
{
if(L.length!=0)
{
for(int i=0;i<L.length;i++)
printf("%d ",L.data[i]);
printf("\n");
return OK;
}
else
{
printf("当前顺序表为空!\n");
return ERROR;
}
}
bool Insert(Sqlist L){
int k;
printf("请输入要插入的数据个数:")
scanf("%d",&k);
if(L.length+k>MAXSIZE)
{
printf("超出线性表的长度!\n");
return ERROR;
}
printf("请逐个输入你要插入的元素:\n");
for(int i=0;i<k;i++){
scanf("%d",&L.data[i]);
L.length++;
}
}
void Menu(){
printf("**************************\n");
printf("1.打印线性表\n");
printf("2.删除元素\n");
printf("3.插入元素\n");
printf("4.检查是否为空表\n");
printf("5.按位置查询数据\n");
printf("6.逐个插入数据\n");
printf("7.当前线性表的长度\n");
printf("8.清空线性表\n");
printf("9.初始化\n");
printf("10.查找元素位置(第一次出现)\n");
printf("0.退出系统\n");
printf("请输入你要进行的操作:\n");
}
int main(){
Sqlist L;//声明一个线性表
Initlist(&L);//线性表的第一次初始化,为线性表分配存储空间
int Choice; //定义与菜单相匹配的选择变量Choice
while(1){//对菜单栏的打印和用户要做的选择进行循环更新
Menu();//打印菜单
scanf("%d",&Choice);//从键盘获取用户的选择
switch(Choice){ //使用switch函数进行操作匹配
case 1:ListTraverse(L);break; //打印线性表
case 2:ListDelete(&L);break;//删除一个元素
case 3:Listinsert(&L);break;//在指定位置插入元素
case 4:ListEmpty(L);break;//检查是否为空表
case 5:GetElem(L);break;//按位置查询线性表元素
case 6:Insert(L);break;//按顺序逐个对线性表进行插入
case 7:Listlength(L);break;//当前线性表的长度
case 8:ClearList(&L);break;//一键清空线性表
case 9:Initlist(&L);break;//对线性表进行初始化操作
case 10:locateElem(L);break;//查找元素位置(第一次出现)
case 0:exit(0);//退出系统
}
}
return 0;
}
最后,又到了我的宇宙免责声明 环节了:关于本篇博客是我(新手小白)对于线性表的顺序存储结构的一些粗陋的认识,无论是认识还是代码中,肯定会有一些错误,欢迎大家指正,给予意见。如果本篇小结不符合您的认知,亦或者对本篇博客不满意,可以将其当做笑话。最后,希望和大家一起进步,一同努力。