顺序表是线性表的一种,其定义为:线性表中所有数据元素根据顺序存储结构,按其逻辑顺序依此存储在一组连续的内存单元中,用这种存储形式存储的线性表成为顺序表。
其特点是:
- 逻辑关系相邻的两个数据元素在物理位置上页相邻。
- 结构简单,便于理解。
在课堂上老师一般都只交授定长顺序表,但是在我们私下练习时会发现定长顺序表某种程度上来说和数组没有什么太大的区别,而且设置的长度也很容易浪费,这种资源的浪费时我们在编写代码过程中需要尽量避免的。
不定长顺序表有两个优点:1.可以避免空间的浪费。2.可以省去我们为了实际问题所要考虑的数组长度。那么说了这么多到底该如何编写不定长顺序表的,这里我们需要引入两个函数:malloc和realloc。
malloc函数:
malloc函数用于动态内存分配,它会申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址。
其函数原型为:
void *malloc(unsigned int size);
用例:
int main()
{
int *a = (int*)malloc(sizeof(int)*10);
//上面一行代码表示整型指针类型的a申请到了40个字节大小的内存
return 0;
}
realloc函数:
语法:
指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
功能:
改变以申请内存的大小。
注意:
新的大小可大可小(如果新的大小大于原内存大小,则新分配部分不会被初始化;如果新的大小小于原内存大小,可能会导致数据丢失 )
用例:
int main()
{
int *a = (int*)malloc(sizeof(int)*10);
//上面一行代码表示整型指针类型的a申请到了40个字节大小的内存
a = (int*)realloc(sizeof(int)*20);
//上面一行代码表示将原先a申请到的40个字节大小的内存扩展到了80个字节
return 0;
}
而不定长顺序表主要就是根据realloc来进行对内存不断的扩展已达到节省资源。
话不多说我们进入不定长顺序表的编写,首先我们定义结构体如下:
typedef struct Seqlist
{
ElemType *str; //定义指向存储数据内存的指针,ElemType为数据类型可为int,char等等。
int cutsize;//当前顺序表长度
int MAXSIZE;//最大长度
}Seqlist,*pSeqlist;
初始化顺序表:
pSeqlist InitSeqlist() //初始化
{
pSeqlist L;
L = (pSeqlist)malloc(sizeof(pSeqlist));
L->cutsize = 0;
L->str = (ElemType*)malloc(sizeof(ElemType)*InitSize);
L->MAXSIZE = InitSize;
return L;
}
判空:
bool IsEmpty(pSeqlist L)//判断顺序表是否为空
{
return L->cutsize == 0;
}
判满:
bool IsFull(pSeqlist L)//判断顺序表是否满
{
return L->cutsize == L->MAXSIZE;
}
扩容:
void Extend(pSeqlist L) //扩充顺序表容量
{
L->str = (ElemType*)realloc(L->str,sizeof(ElemType) * L->MAXSIZE * 2);
L->MAXSIZE *= 2;
}
尾部插入数据:
void PushData(pSeqlist L,ElemType val) //尾部直接插入数据
{
L->str[L->cutsize] = val;
L->cutsize++;
}
按位置插入:
void Insert(pSeqlist L,ElemType val,int pos)//按位置插入
{
if(IsFull(L))
{
Extend(L);
}
for(int i=L->cutsize-1;i>=pos-1;i--)
{
L->str[i+1] = L->str[i];
}
L->str[pos-1] = val;
L->cutsize++;
}
按位置删除:
void Del(pSeqlist L,int pos)//按位置删除
{
if(IsEmpty(L))
{
return;
}
for(int i=pos;i<L->cutsize;i++)
{
L->str[i-1] = L->str[i];
}
L->cutsize--;
}
打印顺序表:
void Show(pSeqlist L)//打印顺序表
{
for(int i = 0 ; i<L->cutsize ; i++)
{
printf("%d\n",L->str[i]);
}
}
主函数调用:
int main()
{
pSeqlist L;
L = InitSeqlist();//初始化顺序表
for(int i=0;i<16;i++)
{
if(IsFull(L))
{
Extend(L);
}
PushData(L,i+1);
}
Insert(L,90,5);//在第五个位置插入90
Del(L,1);//将第一个位置数据删除
Show(L);
}
结果如下:
代码附录:
#include <stdio.h>
#include <stdlib.h>
#define InitSize 10
typedef int ElemType;
typedef struct Seqlist
{
ElemType *str;
int cutsize;
int MAXSIZE;
}Seqlist,*pSeqlist;
pSeqlist InitSeqlist() //初始化
{
pSeqlist L;
L = (pSeqlist)malloc(sizeof(pSeqlist));
L->cutsize = 0;
L->str = (ElemType*)malloc(sizeof(ElemType)*InitSize);
L->MAXSIZE = InitSize;
return L;
}
bool IsEmpty(pSeqlist L)//判断顺序表是否为空
{
return L->cutsize == 0;
}
bool IsFull(pSeqlist L)//判断顺序表是否满
{
return L->cutsize == L->MAXSIZE;
}
void Extend(pSeqlist L) //扩充顺序表容量
{
L->str = (ElemType*)realloc(L->str,sizeof(ElemType) * L->MAXSIZE * 2);
L->MAXSIZE *= 2;
}
void PushData(pSeqlist L,ElemType val) //尾部直接插入数据
{
L->str[L->cutsize] = val;
L->cutsize++;
}
void Insert(pSeqlist L,ElemType val,int pos)//按位置插入
{
if(IsFull(L))
{
Extend(L);
}
for(int i=L->cutsize-1;i>=pos-1;i--)
{
L->str[i+1] = L->str[i];
}
L->str[pos-1] = val;
L->cutsize++;
}
void Del(pSeqlist L,int pos)//按位置删除
{
if(IsEmpty(L))
{
return;
}
for(int i=pos;i<L->cutsize;i++)
{
L->str[i-1] = L->str[i];
}
L->cutsize--;
}
void Show(pSeqlist L)//打印顺序表
{
for(int i = 0 ; i<L->cutsize ; i++)
{
printf("%d\n",L->str[i]);
}
}
int main()
{
pSeqlist L;
L = InitSeqlist();//初始化顺序表
for(int i=0;i<16;i++)
{
if(IsFull(L))
{
Extend(L);
}
PushData(L,i+1);
}
Insert(L,90,5);//在第五个位置插入90
Del(L,1);//将第一个位置数据删除
Show(L);
}