线性表-顺序存储结构
下面是用c语言实现的线性表,顺序存储结构,是用一维数组实现的,即把第一个数据元素存到数组下标为0的位置中,接着把线性表相邻的元素存储在数组相邻的位置。这种顺序存储方式优点是可以快速的存取表中任一位置的元素,但是插入和删除需要移动大量元素,当线性表变化较大时,难以确定存储空间的容量,因为这种存储方式需要提前确定数组的长度,下面的MAXSIZE就是提前指定的数组长度。
正如上面介绍,线性表顺序存储结构是利用数组实现的,那么该线性表的基本操作,无非是对数组中元素的操作,那么我们很容易想到操作有:给数组特定位置添加元素、删除特定位置元素、确定线性表当前长度、清空线性表、初始化线性表等等,可以参考下面程序学习。
注:详细内容可以参考程杰的《大话数据结构》,下面代码是这本书提供的源代码
//
// main.c
// 线性表-顺序存储
//
//
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /*线性表最大长度 */
typedef int Status;
typedef int ElemType;
Status visit(ElemType c)
{
printf("%d ",c);
return OK;
}
typedef struct
{
ElemType data[MAXSIZE]; /* 数组,存储数据元素 */
int length; /* 线性表当前长度 */
}SqList;
/* 初始化线性表*/
Status InitList(SqList *L)
{
L->length=0; /* L是指向链表的指针,L->length是指该指针指向链表中的length元素 */
return OK;
}
/* 判断线性表是否为空 */
Status ListEmpty(SqList L)
{
if(L.length==0)
return TRUE;
else
return FALSE;
}
/* 清空线性表 */
Status ClearList(SqList *L)
{
L->length=0;
return OK;
}
/* 返回线性表当前长度 */
int ListLength(SqList L)
{
return L.length;
}
/* 获取线性表第i个元素,并用e返回*/
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;
}
/* 判断线性表中是否存在值为e的元素,若存在,返回它的位置 */
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)//不存在该元素,返回0
return 0;
return i+1;
}
/* 将e元素插入到线性表的第i个位置 */
Status ListInsert(SqList *L,int i,ElemType e)
{
int k;
if (L->length==MAXSIZE) /* 链表最大长度 */
return ERROR;
if (i<1 || i>L->length+1)/* 插入位置大于表长,或者小于1,报错 */
return ERROR;
if (i<=L->length) /* 插入位置不在表尾 */
{
for(k=L->length-1;k>=i-1;k--) /*将第i个位置至最后元素都向后移动一位 */
L->data[k+1]=L->data[k];
}
L->data[i-1]=e; /* 将数据e插入到第i个位置 */
L->length++;
return OK;
}
/* 删除线性表中第i个元素,并用e返回被删除的元素 */
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;
}
/* 打印线性表中每个元素 */
Status ListTraverse(SqList L)
{
int i;
for(i=0;i<L.length;i++)
visit(L.data[i]);
printf("\n");
return OK;
}
/* */
void unionL(SqList *La,SqList Lb)
{
int La_len,Lb_len,i;
ElemType e;
La_len=ListLength(*La);
Lb_len=ListLength(Lb);
for (i=1;i<=Lb_len;i++)
{
GetElem(Lb,i,&e); //获取链表Lb中第i个元素,并用e返回
if (!LocateElem(*La,e)) //判断条件,若链表La中不存在值为e的元素,执行下面操作
ListInsert(La,++La_len,e);//将e插入到链表La的表尾
}
}
int main()
{
SqList L;
ElemType e;
Status i;
int j,k;
i=InitList(&L);
printf("初始化L后:L.length=%d\n",L.length);
for(j=1;j<=5;j++)
i=ListInsert(&L,1,j);
printf("在L的表头依次插入1~5后:L.data=");
ListTraverse(L);
printf("L.length=%d \n",L.length);
i=ListEmpty(L);
printf("L 是否为空:i=%d(1:是 0:否)\n",i);
i=ClearList(&L);
printf("清空L后:L.length=%d\n",L.length);
i=ListEmpty(L);
printf("L 是否:i=%d(1:是 0:否)\n",i);
for(j=1;j<=10;j++)
ListInsert(&L,j,j);
printf("在L的表尾依次插入1~10后:L.data=");
ListTraverse(L);
printf("L.length=%d \n",L.length);
ListInsert(&L,1,0);
printf("在L的表头插入0后:L.data=");
ListTraverse(L);
printf("L.length=%d \n",L.length);
GetElem(L,5,&e);
printf("第5个元素的值为:%d\n",e);
for(j=3;j<=4;j++)
{
k=LocateElem(L,j);
if(k)
printf("第%d个元素的值为%d\n",k,j);
else
printf("没有值为%d的元素\n",j);
}
k=ListLength(L);
for(j=k+1;j>=k;j--)
{
i=ListDelete(&L,j,&e);
if(i==ERROR)
printf("删除第%d个数据失败\n",j);
else
printf("删除第%d个的元素值为:%d\n",j,e);
}
printf("依次输出L的元素:");
ListTraverse(L);
j=5;
ListDelete(&L,j,&e); /* …æ≥˝µ⁄5∏ˆ ˝æ› */
printf("删除第%d个的元素值为:%d\n",j,e);
printf("依次输出L的元素:");
ListTraverse(L);
SqList Lb;
i=InitList(&Lb);
for(j=6;j<=15;j++)
i=ListInsert(&Lb,1,j);
unionL(&L,Lb);
printf("依次输出合并了Lb的L的元素:");
ListTraverse(L);
return 0;
}
运行结果如下:
初始化L后:L.length=0
在L的表头依次插入1~5后:L.data=5 4 3 2 1
L.length=5
L 是否为空:i=0(1:是 0:否)
清空L后:L.length=0
L 是否:i=1(1:是 0:否)
在L的表尾依次插入1~10后:L.data=1 2 3 4 5 6 7 8 9 10
L.length=10
在L的表头插入0后:L.data=0 1 2 3 4 5 6 7 8 9 10
L.length=11
第5个元素的值为:4
第4个元素的值为3
第5个元素的值为4
删除第12个数据失败
删除第11个的元素值为:10
依次输出L的元素:0 1 2 3 4 5 6 7 8 9
删除第5个的元素值为:4
依次输出L的元素:0 1 2 3 5 6 7 8 9
依次输出合并了Lb的L的元素:0 1 2 3 5 6 7 8 9 15 14 13 12 11 10
Program ended with exit code: 0
ps:读这段代码时候,开始有一点不很清楚地方是L->length和L->data这种表达,后来才明白,这中表述中,L是一个指针变量,指向SqList的指针,而L->length的意思就是该指针L指向的SqList结构中的length。
可以通过下面小程序更清晰了解:
#include <iostream>
struct pero{
char name[20];
int age;
int tall;
};
int main(int argc, const char * argv[]) {
pero wang={
"weiwei",
26,
180
};
pero* pst=&wang;
std::cout<<wang.age<<std::endl;
pst->age=20;
std::cout<<wang.age<<std::endl;
return 0;
}
运行结果:26和20
可见,通过pst->age对pst指针指向的wang中的age元素进行了赋值操作。