线性表顺序表示
线性表顺序表示概念解释
所谓线性表的顺序表示,事实上也就是线性表的顺序存储结构。意思也就是什么呢?我们可以给出这样的定义或者说规矩:
<1>每个元素所需要的内存单元为 ∫ ;
<2>首个元素的存储地址为b或者LOC(a-i)通常称为起始位置或基地址;
那线性表中任意一个数据元素的存储位置等于第一个数据元素的存储位置加上,第n个元素减一乘以存储单元。
LOC = b + (i-1) ∫ ;
对应的后一个数据元素的存储位置等于后一个数据元素的存储位置加上存储单元。
LOC(i+1) = LOC(i) + ∫ ;
注:LOC(line of communication)
说白了,线性表这种存储位置也就是中学所学的,等差数列,对比记忆即可。
线性表的这种机内表示称作的顺序存储结构或顺序映像(sequential mapping)。它的特点也就是,以元素在计算机内的物理位置相邻来表示线性表中数据元素之间的逻辑结构。每个数据元素的存储位置都和线性表的起始位置相差一个和数据元素在线性表中的位序成正比的常熟。
事实上,没那么复杂,就三个数据信息,一个线性表中的位序,从1开始到n。对应的数组下标从0开始到n-1。而存储地址,从 b开始到b+(maxxian - 1)* ∫ ;
线性表的顺序结构代码实现部分
(1)顺序表的初始化
思路分析:
顺序表的初始化(initialize list)就是创建一个空表,即我们需要使这个顺序表的长度为0。
实际操作:
这里我们定义了一个无返回值类型函数名为InitList,形参为结构体指针参数L。要使顺序表的长度为0,即使结构体成员的length值为0,使用指针参数L,调用结构体成员Length并使其数值为0。
void InitList( SeqList *L)
{
L ->Length = 0;
}
(2)顺序表的建立
思路分析:
顺序表的建立(create list),就是要为这个顺序表添加数据,那我们就需要循环为这个数表进行赋值。既然添加数据,就要知道需要添加多少数据,就需要获取用户键盘输入的数值以确定所添加的数据数量。
实际操作:
第一步:使用scanf函数获取用户输入的数据数量值,赋值给n
第二步:调用顺序表建立函CreateList()并传入两个形参,一个是结构体指针参数L,和数据数量值n。使用for循环为顺序表赋值。
void CreateList(SeqList *L,int n)
{
int i;
printf("请输入%d个整数:",n);
for ( i = 0; i < n; i++)
{
scanf("%d",&L->data[i]);
}
L->Length = i;
}
对应的主函数中的调用部分
case '1':
InitList(&L);
printf("请输入建立线性表的个数:");
scanf("%d",&n);
CreateList(&L,n);
printf("建立的线性表为:");
DispList(&L);
break;
(3)查找操作-按位置查找和按值查找
查找操作分为:
1.按位置查找(get elem),也就是按表内数据元素排序序号查找。
思路分析:
顺序表是开辟了一段连续的内存空间,所以表内元素就是按照1~n的顺序排列的,既然如此,我们只需要判断用户输入的查询位置是否存在于表内,随后用数组索引值进行引用即可。需要注意的是数组索引值从0开始,表内顺序从1开始。
实际操作:
第一步,传入结构体指针L,用户查询位置参数i,和整型指针变量x用来存放查找到的数据值的地址。
第二步,判断i是否在顺序表的1~Lenth范围内,如果在将索引值为i-1的数据值赋值给指针变量x,并返回1.如果不在在放回0.
int GetElem(SeqList *L,int i,DataType *x)
{
if (i<1||i>L->Length)
{
return 0;
}
else
{
*x = L->data[i-1];
return 1;
}
}
2.按值查找位置(Locate),也就是查找某一个值在表内的位置
思路分析:
按照查找,类型于按位置查找,只需遍历顺序表,找到与之匹配的数组位置即可。
实际操作:
第一步,传值,传入结构体指针L,用户需要查询的数值x。
第二步,遍历表中数据,找到与x匹配的数组下标i,如果下标i超过表长,则返回0,如果没有则返回i+1即顺序表的序号值。
int Locate(SeqList *L,DataType x)//按值查找
{
int i;
/*while (i<L->Length && L->data[i] != x)
{
i++;
}*/
for(i=0;L->data[i] != x;i++){};
if (i>=L->Length)
{
return 0;
}
else
{
return i+1;
}
}
(4)插入操作
思路分析:
所谓插入就是在原有的线表中插入一个新的数据,既然是插入新数据就要考虑几件事,首先这个线性表是否还有剩余空间,其次是用户需要插入的位置是否在这个线性表的存储范围内。既然在这个位置插入一个数据,那这个位置后续的数据都要依次后移。如果位于最后一个则不需要依次后移。
实际操作:
第一步:传值,传入结构体指针L,用户输入的插入位置i,需要插入的数值x
第二步:判断这个线性表的长度length是否长于最大存储长度MAXLEN,如果储存内存已满则输出顺序表已满并放回-1;
第三步:判断用户输入的插入位置i是否位于顺序表的长度范围内,如果不在则输出插入位置有误,并放回-1;
第四步:判断用户输入的插入位置是否位于最后,如果i等于length+1则直接插入到尾部。使数值下标为i-1的位置等于这个插入数值x,如果插入成功放回1;
第五步:如果不在尾插入,则从最后一位开始依次向后移动,直到i的位置。将前一结点的数据赋值给后一位,最后将x的值插入到索引值为i-1的位置。如果插入成功放回1;
int InsElem(SeqList *L,int i,DataType x)
{
int j;
if (L->Length>=MAXLEN)
{
printf("顺序表已满!");
return -1;
}
if (i<1 || i>L->Length+1)
{
printf("插入位置出错!");
return 0;
}
if (i == L->Length+1)
{
L->data[i-1] = x;
L->Length++;
return 1;
}
for ( j = L->Length-1; j >= i-1; j--)
{
L->data[j+1] = L->data[j];
}
L->data[i-1] = x;
L->Length++;
return 1;
}
(5)删除操作
思路分析:
删除操作(delete elem)就是删除线性表中已有的数据,首先要知道用户想要删除的位置,和插入相同的是删除也需要进行移动操作,只是需要覆盖掉前一个数据值,依次前移。
实际操作:
第一步:传值,传入结构体指针L,用户输入的插入位置i,需要删除存放起来的数值x
第二步:判断这个线性表的长度length是否长于最大存储长度MAXLEN,如果储存内存已满则输出顺序表已满并放回0;
第三步:判断用户输入的插入位置i是否位于顺序表的长度范围内,如果不在则输出插入位置有误,并放回0;
第四步:将需要删除的数组存入x
第五步:使用循环语句,循环向前依次移动数据。
int DelElem(SeqList *L,int i,DataType *x)
{
int j;
if (L->Length == 0)
{
printf("顺序表为空!");
return 0;
}
if (i<1 || i>L->Length)
{
printf("不存在第i个元素");
return 0;
}
*x = L->data[i-1];
for ( j = i; j < L->Length; j++)
{
L->data[j-1] = L->data[j];
}
L->Length--;
return 1;
}
(6)输出表中元素操作
思路分析:
循环输出数组中的值即可。
实际操作:
使用循环语句输入
void DispList(SeqList *L)
{
int i;
for ( i = 0; i < L->Length; i++)
{
printf("%5d ",L->data[i]);
}
}
附录 程序清单
#include<stdio.h>
#include<stdlib.h>
/*顺序表的类型定义*/
#define MAXLEN 100
//使用typedef定义新类型名,语法typedef 原类型名 新类型名;
typedef int DataType;
/*typedef 原类型名 新类型名;*/
typedef struct
{
DataType data[MAXLEN];//存放线性表的数组
int Length;//length是顺序表的长度
}SeqList;
SeqList L;
/*1.顺序表的初始化*/
void InitList( SeqList *L)
{
L ->Length = 0;
}
/*2.顺序表的建立*/
void CreateList(SeqList *L,int n)
{
int i;
printf("请输入%d个整数:",n);
for ( i = 0; i < n; i++)
{
scanf("%d",&L->data[i]);
}
L->Length = i;
}
/*3.查找操作*/
int GetElem(SeqList *L,int i,DataType *x)//按位置查找
{
if (i<1||i>L->Length)
{
return 0;
}
else
{
*x = L->data[i-1];
return 1;
}
}
int Locate(SeqList *L,DataType x)//按值查找
{
int i;
/*while (i<L->Length && L->data[i] != x)
{
i++;
}*/
for(i=0;L->data[i] != x;i++){};
if (i>=L->Length)
{
return 0;
}
else
{
return i+1;
}
}
/*4.插入操作*/
int InsElem(SeqList *L,int i,DataType x)
{
int j;
if (L->Length>=MAXLEN)
{
printf("顺序表已满!");
return -1;
}
if (i<1 || i>L->Length+1)
{
printf("插入位置出错!");
return 0;
}
if (i == L->Length+1)
{
L->data[i-1] = x;
L->Length++;
return 1;
}
for ( j = L->Length-1; j >= i-1; j--)
{
L->data[j+1] = L->data[j];
}
L->data[i-1] = x;
L->Length++;
return 1;
}
/*5.删除操作*/
int DelElem(SeqList *L,int i,DataType *x)
{
int j;
if (L->Length == 0)
{
printf("顺序表为空!");
return 0;
}
if (i<1 || i>L->Length)
{
printf("不存在第i个元素");
return 0;
}
*x = L->data[i-1];
for ( j = i; j < L->Length; j++)
{
L->data[j-1] = L->data[j];
}
L->Length--;
return 1;
}
/*6.输出表中元素操作*/
void DispList(SeqList *L)
{
int i;
for ( i = 0; i < L->Length; i++)
{
printf("%5d ",L->data[i]);
}
}
/*7.显示菜单函数*/
void Menu()
{
printf(" 顺序表的各种操作 \n");
printf("=======================================\n");
printf("| 1--建立顺序表 ||\n");
printf("| 2--插入元素 ||\n");
printf("| 3--删除元素 ||\n");
printf("| 4--按位置查找元素 ||\n");
printf("| 5--按元素值查找其在表中的位置||\n");
printf("| 6--求顺序表的长度 ||\n");
printf("| 0--返回 ||\n");
printf("=======================================\n");
printf("请输入你要选择的菜单号:");
}
/*主函数*/
int main()
{
SeqList L;
DataType x;
int n,i,loc;
char ch1,ch2,a;
ch1 = 'y';
while (ch1 == 'y'|| ch1 == 'Y')
{
Menu();
scanf("%c",&ch2);
getchar();
switch (ch2)
{
case '1':
InitList(&L);
printf("请输入建立线性表的个数:");
scanf("%d",&n);
CreateList(&L,n);
printf("建立的线性表为:");
DispList(&L);
break;
case '2':
printf("请输入你要插入的位置:");
scanf("%d",&i);
printf("请输入你要插入的元素值:");
scanf("%d",&x);
if (InsElem(&L,i,x))
{
printf("已成功在第%d的位置上插入%d,插入后的线性表为:\n",i,x);
DispList(&L);
}
else
{
printf("输入插入的参数错误!");
}
break;
case '3':
printf("请输入要删除元素的位置:");
scanf("%d",&i);
if (DelElem(&L,i,&x))
{
printf("已成功在第%d的位置上删除%d,删除后的线性表为:\n",i,x);
DispList(&L);
}
else
{
printf("输入删除的参数错误!");
}
break;
case '4':
printf("请输入要查看表中元素的位置(从1开始):");
scanf("%d",&i);
if (GetElem(&L,i,&x))
{
printf("当前线性表第%d个元素的值为:%d",i,x);
}
else
{
printf("输入的位置错误!");
}
break;
case '5':
printf("请输入要查找的元素值为:");
scanf("%d",&x);
loc = Locate(&L,x);
if (loc)
{
printf("查找元素值为%d的位置为:%d",x,loc);
}
else
{
printf("此表中无此元素!");
}
break;
case '6':
printf("当前线性表的长度为:%d",L.Length);
break;
case '0':
ch1 = 'n';
break;
default:
printf("输入有误,请输入0~6进行选择。");
break;
}
if (ch2 != '0')
{
printf("\n按回车键继续,按任意键返回主菜单!\n");
a = getchar();
if (a != '\xA')
{
getchar();
ch1 = 'n';
}
}
}
}