赞
踩
线性表的顺序存储又称顺序表。它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻。因此,顺序表的特点是表中元素的逻辑顺序和其物理顺序相同。
- #define Maxsize 10 //定义线性表的最大长度
- typedef struct
- {
- ElemType data[MaxSize]; //顺序表的元素(Elemtype为元素的类型,可替换为int,char,float等)
- int length; //顺序表的当前长度(表中元素个数)
- }SqList; //顺序表的类型定义
一维数组可以静态分配,也可以动态分配。在静态分配时,由于数组的大小和空间事先已经固定,一旦空间占满,再加入新的数据就会溢出,进而导致程序崩溃。
- #define InitSize 100 //表长度的初始定义
- typedef struct
- {
- int *data; //指示动态分配数组的指针,这里的int可替换为其他类型
- int length; //数组的当前个数
- int MaxSize; //数组的最大容量
- }SeqList; //动态分配数组顺序表的类型定义
-
- //C语言的初始动态分配语句:
- L.data=(ElemType *)malloc(sizeof(ElemType)*InitSize);//动态申请一整片的内存空间
-
- //初始化为
- void InitList(SeqList *L){
- (*L).data=(int*)malloc(InitSize*sizeof(int));//这里的int可替换为其他类型
- (*L).length=0;
- (*L).MaxSize=InitSize;
- }
在动态分配时,存储数组的空间在程序执行过程中通过动态存储分配语句分配的,一旦数据空间占满,就另外开辟一块更大的存储空间,用于替换原来的存储空间,从而达到扩充存储数组空间的目的,不需要为线性表一次性地划分所有空间。
注:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时动态决定。
代码如下(示例):
- //初始化
- bool InitList(SqList *L){
- for (int i = 0; i < MaxSize; i++)
- {
- (*L).data[i]=0; //利用循环将表中的数据都为0
- }
- (*L).length=0; //将length也置为0,意思是当前表中无数据
- return true;
- }
由于在位序为i的位置,增加一个元素,则原来位序为i及位序i之后的元素都要往后移一位,将位序i给空出来,用来存放要插入的新元素。例:位序i后一位为i+1,位序i的要往后移一位,就是将位序i处的值放在位序为i+1处,因为数组中下标从0开始的,则在数组中表现为data[i]=data[i-1];
- // 插入
- 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;
- }
由于删除了一个元素,表中会空出来一个位置,即位序i会空出来,这时候就需要将位序i之后的值往前移一位 ,例:位序i后一位为i+1,要往前移一位,就是将位序i+1处的值放在位序为i处,因为数组中下标从0开始的,则在数组中表现为data[i-1]=data[i];
- // 删除
- 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;
- }
- //打印表
- 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时,此时表中无数据元素
- }
- }
- //查找
- //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;
- }
- }
- }
在主函数中,为了方便我就设计插入了两个值,然后依次打印表中数据,按位查找,按值查找,删除,打印表进行。
- #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");
- }
总结
顺序表的优点:
1.存储密度大:每个存储结点只存储数据本身
2.可以随机存取表中任一元素
顺序表的缺点:
1.在插入、删除某一元素时,需要移动大量元素
2.大片连续空间分配不方便
3.改变容量不方便
文章还有瑕疵,请各位指正。
链表的操作和链表的一些不易理解的知识会在下一篇介绍,如:LNode *和LinkList的区别,和在C语言中如何实现链表的操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。