详解顺序表
1. 顺序表的定义及其特点;
2. 顺序表的运算(概述);
3. 顺序表的实现(详细的介绍及C程序代码、执行结果);
4. 完整的Demo;
5. 小结;
6. 参考文献
----------------------------------------
1. 顺序表的定义及其特点
定义:顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
特点:(1)存储结构:顺序表的存储结构是一段连续的内存空间,数据元素按照线性顺序存储,可以通过元素下标进行访问。
(2)固定大小:顺序表的大小是固定的,一旦创建后就不能动态扩容或缩小,因此需要事先确定存储元素的个数。
(3)访问速度快:由于顺序表的元素存储在连续的内存空间中,因此可以通过下标直接访问元素,访问速度较快。
(4)插入、删除操作效率低:由于顺序表的存储结构是连续的,因此在插入或删除元素时需要将后续的元素全部向后或向前移动,效率较低。
(5)适合静态存储数据:由于顺序表的大小是固定的,因此适合存储静态数据,不适合动态增删的情况。
2. 顺序表的运算(概述)
(1)插入操作:顺序表的插入操作通常有两种方式,一种是在表尾插入元素,另一种是在表中的任意位置插入元素。对于表尾插入元素,需要先判断表是否已满,如果未满,则将元素插入表尾。对于在表中任意位置插入元素,需要先将插入位置及其之后的元素后移,然后再将要插入的元素放入合适的位置。
(2)删除操作:顺序表的删除操作也有两种方式,一种是删除表尾元素,另一种是删除表中的任意元素。对于删除表尾元素,直接将表尾元素删除即可。对于删除表中任意元素,需要先找到要删除的元素的位置,然后将该位置之后的元素前移,最后将表中的元素个数减1。
(3)查找操作:顺序表的查找操作可以根据元素的值或者位置进行。如果是根据元素的值进行查找,则需要遍历整个表,逐一比较元素的值。如果是根据位置进行查找,则直接返回该位置的元素值即可。
(4) 遍历操作:顺序表的遍历操作可以遍历整个表,也可以只遍历部分元素。遍历整个表可以使用循环结构,依次输出每个元素的值。遍历部分元素则可以通过设置起始位置和结束位置来实现。
3. 顺序表的实现(详细的介绍及C程序代码、执行结果)
(1)初始化
//初始化
bool InitList(SqList *L){
for (int i = 0; i < MaxSize; i++)
{
(*L).data[i]=0; //利用循环将表中的数据都为0
}
(*L).length=0; //将length也置为0,意思是当前表中无数据
return true;
}
(2)插入
// 插入
bool ListInsert(SqList *L,int i,int e){
if(i<1||i>(*L).length+1){
printf("要插入的位置错误\n"); //只能在表中第一个元素和(最后一个元素的后一位)两者之间插入,
return false; //按位序的话,i的值要满足1<=i<=length+1
}
if((*L).length>=MaxSize) {
printf("存储空间已满!\n"); //如果length大于等于Maxsize说明表已满,插入数据失败
return false;
}
int j;
for ( j=(*L).length; j>=i; j--) //从最后一位开始到第i位(包括第i位),从后往前,
{ //将值往后移一位,从而将第i位给空出来(这里的i都为位序,从1开始)
(*L).data[j]=(*L).data[j-1];
}
(*L).data[i-1]=e; //将要插入的值放入位序为i中,即在数组中为data[i-1]
(*L).length++; //由于表插入了一个元素,故length的值要加1
return true;
}
(3)删除
// 删除
bool ListDelete(SqList *L,int i,int *e){
if(i<1||i>(*L).length){
printf("要删除的位置错误\n"); //判断i值是否合法
return false;
}
(*e)=(*L).data[i-1]; //将位序i中的值赋予e,用于返回
int j;
for (j=i;j<(*L).length;j++) //利用循环从位序为i处到位序为的length最后一个元素,从前往后依次往前移动一个元素
{
(*L).data[j-1]=(*L).data[j];
}
(*L).length--; //由于删除一个元素,所以length减一
return true;
}
(4)打印表
//打印表
void printList(SqList L){
for (int i = 0; i < L.length; i++) //i值从0开始
{
printf("第%d的值为:%d\n",i+1,L.data[i]); //利用数组下标依次将表中数据元素打印出来
}
if(L.length==0){
printf("表中没有数据!\n"); //length为0时,此时表中无数据元素
}
}
(5)查找(按位查找和按值查找)
//查找
//1.按位查找
bool GetElem(SqList L,int i){
if (i<1||i>L.length)
{
printf("要查询的值的位置不合法!\n");
return false; //如果i值不合法(i只能在1<=i<=length内),则查找失败
}
printf("表中第%d个元素为:%d\n",i,L.data[i-1]);//输出表中位序为i的值
return true;
}
//2.按值查找
bool LocateElem(SqList L,int e){
if (L.length==0)
{
return false;
}
for (int i = 0; i < L.length; i++)//利用循环依次查找表中数据元素
{
if (L.data[i]==e) //并依次和要查找的e值进行比较,如果相同则在表中找到e值,输出
{
printf("此值%d为表中第%d个元素\n",e,i+1);
return true;
}
}
}
(6)执行结果
ret= 111
输入要插入的位置:1
输入要插入的值:5
第1的值为:5
输入要插入的位置:2
输入要插入的值:8
第1的值为:5第2的值为:8
输入要查询第几位的值:2
表中第2个元素为:8输入要查询的值:
5
此值5为表中第1个元素输入要删除的位置:
2
删除的值为:8第1的值为:5
请按任意键继续...
4.完整的Demo
#include<stdio.h>
#include<stdbool.h> //如果要用bool类型,要加上这个头文件
#include<stdlib.h>
// 顺序表(静态分配)
#define MaxSize 10
typedef struct
{
int data[MaxSize];
int length;
}SqList;
//初始化
bool InitList(SqList *L){
for (int i = 0; i < MaxSize; i++)
{
(*L).data[i]=0; //利用循环将表中的数据都为0
}
(*L).length=0; //将length也置为0,意思是表中无数据
return true;
}
// 判断顺序表是否为空
int IsEmpty(SqList L){
if (L.length==0)
{
return 111;
}
else
{
return 000;
}
}
//打印表
void printList(SqList L){
for (int i = 0; i < L.length; i++) //i值从0开始
{
printf("第%d的值为:%d\n",i+1,L.data[i]); //利用数组下标依次将表中数据元素打印出来
}
if(L.length==0){
printf("表中没有数据!\n"); //length为0时,此时表中无数据元素
}
}
// 插入
bool ListInsert(SqList *L,int i,int e){
if(i<1||i>(*L).length+1){
printf("要插入的位置错误\n"); //只能在表中第一个元素和(最后一个元素的后一位)两者之间插入,
return false; //按位序的话,1<=i<=length+1
}
if((*L).length>=MaxSize) {
printf("存储空间已满!\n"); //如果length大于等于Maxsize说明表已满,插入数据失败
return false;
}
int j;
for ( j=(*L).length; j>=i; j--) //从最后一位开始到第i位(包括第i位),从后往前,
{ //将值往后移一位,从而将第i位给空出来(这里的i都为位序,从1开始)
(*L).data[j]=(*L).data[j-1];
}
(*L).data[i-1]=e; //将要插入的值放入位序为i中,即在数组中为data[i-1]
(*L).length++; //由于表插入了一个元素,故length的值要加1
return true;
}
// 删除
bool ListDelete(SqList *L,int i,int *e){
if(i<1||i>(*L).length){
printf("要删除的位置错误\n"); //判断i值是否合法
return false;
}
(*e)=(*L).data[i-1]; //将位序i中的值赋予e,用于返回
int j;
for (j=i;j<(*L).length;j++) //利用循环从位序为i处到位序为的length最后一个元素,从前往后依次往前移动一个元素
{
(*L).data[j-1]=(*L).data[j];
}
(*L).length--; //由于删除一个元素,所以length减一
return true;
}
//查找
//1.按位查找
bool GetElem(SqList L,int i){
if (i<1||i>L.length)
{
printf("要查询的值的位置不合法!\n");
return false; //如果i值不合法(i只能在1<=i<=length内),则查找失败
}
printf("表中第%d个元素为:%d\n",i,L.data[i-1]);//输出表中位序为i的值
return true;
}
//2.按值查找
bool LocateElem(SqList L,int e){
if (L.length==0)
{
return false;
}
for (int i = 0; i < L.length; i++)//利用循环依次查找表中数据元素
{
if (L.data[i]==e) //并依次和要查找的e值进行比较,如果相同则在表中找到e值,输出
{
printf("此值%d为表中第%d个元素\n",e,i+1);
return true;
}
}
}
int main(){
SqList L;
// 初始化
InitList(&L);
// 判断是否为空
int ret; //用来接收判断表是否为空的数据
ret=IsEmpty(L);
printf("ret= %d\n",ret); //表为空输出“111”,表不为空输出“000”
// 第一次插入数据
printf("输入要插入的位置:\n");
int i;int e;
scanf("%d",&i); //输入要插入的位置
printf("输入要插入的值:\n");
scanf("%d",&e); //输入插入的值
ListInsert(&L,i,e);
// 打印表
printList(L);
//第二次插入数据
printf("输入要插入的位置:\n");
scanf("%d",&i);
printf("输入要插入的值:\n");
scanf("%d",&e);
ListInsert(&L,i,e);
// 再次打印表
printList(L);
//按位查找
printf("输入要查询第几位的值:\n");
scanf("%d",&i);
GetElem(L,i);
//按值查找
printf("输入要查询的值:\n");
scanf("%d",&e);
LocateElem(L,e);
// 删除数据
printf("输入要删除的位置:\n");
int n;int e3; //e3用来接收删除所返回的要删除的值
scanf("%d",&n); //输入要删除第几个值
ListDelete(&L,n,&e3);
printf("删除的值为:%d\n",e3); //输出e3
// 打印表
printList(L);
system("pause");
}
5.小结
顺序表的优点:
(1).存储密度大:每个存储结点只存储数据本身
(2).可以随机存取表中任一元素
顺序表的缺点:
(1).在插入、删除某一元素时,需要移动大量元素
(2).大片连续空间分配不方便
(3).改变容量不方便
6.参考文献
1.百度文库
2.c语言数据结构与算法分析