1.顺序表
1.顺序表
定义:一系列物理连续地址的存储单元,用来存储一系列的数据元素,一般是用数组的形式存储,(但和数组还是有一些区别),用来实现对数据的增删查改
比如数组的成员访问是任意的,我可以创建十个元素长度的数组,在下标为0放一个元素,下标为4放一个元素,其他空着也不初始化
但是顺序表强调的就是连续
还记得我们之前写过的动态版本的通讯录吗
https://blog.csdn.net/weixin_71138261/article/details/127030054?spm=1001.2014.3001.5501
其实我们当初的设想就是,如果只用一个固定大小的数组不够完美,这个数据的大小最好能根据我要放多少个数据来确定,这样不会浪费空间
struct contact
{
struct People_Information* date;
int sz;
int capacity;
};
其实在那个程序里这个部分,我们就用到一个结构体来动态存放数据
这就是一个顺序表的思想
把这个程序里面的顺序表部分拿出来我们再巩固一下
//头文件.h
被注释的地方就是静态的顺序表,用到的不多,所以着重看动态的部分
#define _CRT_SECURE_NO_WARNINGS
#pragrama once //防止头文件被多次包含
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//static squential list
//#define LEN 10
typedef int Datatype;
//typedef struct SquList
//{
// int arr[LEN];
// int size;
//}SL;
//dynamic
typedef struct SquList
{
Datatype*squ;
int size;
int capacity;
}SL;
void SquInit(SL*ps); //初始化
void SquPushBack(SL* ps, Datatype x); //尾插
void Destory(SL* ps); //销毁
void PopBack(SL* ps);//尾删
void SquPrint(SL* ps);//打印
//函数实现部分.c
函数实现部分,一些增删查改的函数
#define _CRT_SECURE_NO_WARNINGS
#include "sldlist.h"
void SquInit(SL* ps)
{
assert(ps);
ps->squ=NULL;
ps->capacity = 0;
ps->size = 0;
}
void SquPushBack(SL* ps, Datatype x)
{
assert(ps);
if (ps->size == ps->capacity)
{
int newcapacity = ps->size == 0 ? 4 : ps->capacity * 2;
Datatype*tmp= (Datatype*)realloc(ps->squ, newcapacity * sizeof(Datatype));
if (tmp == NULL)
{
perror("realloc");
exit(-1);
}
ps->squ = tmp;
ps->capacity = newcapacity;
}
ps->squ[ps->size] = x;
ps->size++;
}
void Destory(SL* ps)
{
assert(ps);
if (ps ->squ)
{
free(ps->squ);
ps ->squ= NULL;
}
}
void PopBack(SL* ps)
{
assert(ps->size > 0);
ps->size--;
}
void SquPrint(SL* ps)
{
assert(ps);
for(int i = 0; i < ps->size; i++)
{
printf("%d ", ps->squ[i]);
}
printf("\n");
}
//函数主体.c
#define _CRT_SECURE_NO_WARNINGS
#include "sldlist.h"
#include <stdio.h>
int main()
{
SL sl;
SquInit(&sl);
SquPushBack(&sl, 1);
SquPushBack(&sl, 2);
SquPushBack(&sl, 3);
SquPushBack(&sl, 4);
SquPushBack(&sl, 5);
SquPrint(&sl);
SquPushBack(&sl, 7);
SquPushBack(&sl, 9);
SquPushBack(&sl, 10);
SquPrint(&sl);
PopBack(&sl);
SquPrint(&sl);
Destory(&sl);
return 0;
}
当然,如果这个顺序表只能尾插尾删,那他也太不合格了
所以我们现在增加一些他的功能,包括头插,头删,尾插,尾删,万能插,万能删(指定位置)
新的程序如下
squential.h
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
typedef int type;
typedef struct Squential
{
type* a;
type size;
type capacity;
}SL;
void Init(SL* ps);
void PushFront(SL* ps,type x);
void Print(SL* ps);
void Destory(SL* ps);
void Plus(SL* ps);
void PopFront(SL* ps);
void PushBack(SL* ps,type x);
void PopBack(SL* ps);
void Push(SL* ps, type pos,type x );
void Delete(SL* ps, type pos);
squential.c
#define _CRT_SECURE_NO_WARNINGS
#include "squential.h"
//初始化
void Init(SL* ps)
{
ps->a = NULL;
ps->capacity = 0;
ps->size = 0;
}
//判断一下是不是要扩容
void Plus(SL* ps)
{
assert(ps);
if (ps->capacity == ps->size)
{
type new = ps->capacity == 0 ? 4 : ps->capacity * 2;
type* tmp = (type*)realloc(ps->a,new * sizeof(type));
if (tmp == NULL)
{
perror("realloc");
exit(0);
}
ps->a = tmp;
ps->capacity = new;
}
}
//头插
void PushFront(SL* ps,type x)
{
assert(ps);
Plus(ps);
if (ps->size == 0)
{
ps->a[0] = x;
}
else
{
type end = ps->size-1;
while (end >= 0)
{
ps->a[end+1] = ps->a[end ];
end--;
}
ps->a[0] = x;
}
ps->size++;
}
//打印
void Print(SL* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d", ps->a[i]);
}
printf("\n");
}
//销毁
void Destory(SL* ps)
{
assert(ps);
if (ps->a != NULL)
{
free(ps->a);
ps->a= NULL;
ps->capacity = 0;
ps->size = 0;
}
}
//头删
void PopFront(SL* ps)
{
assert(ps);
if (ps->size == 0)
{
printf("表空\n");
exit(0);
}
else
{
type begin = 1;
while (begin < ps->size)
{
ps->a[begin-1] = ps->a[begin ];
begin++;
}
}
ps->size--;
}
//尾插
void PushBack(SL* ps,type x)
{
assert(ps);
Plus(ps);
if (ps->size == 0)
{
ps->a[0] = x;
}
else
{
ps->a[ps->size] = x;
}
ps->size++;
}
//尾删
void PopBack(SL* ps)
{
assert(ps);
if (ps->size == 0)
{
printf("表空\n");
exit(0);
}
else
{
ps->size--;
}
}
//万能插
void Push(SL* ps,type pos,type x)
{
assert(ps);
Plus(ps);
assert(pos >= 0);
assert(pos <= ps->size);
Plus(ps);
type end= ps->size -1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
//万能删除
void Delete(SL* ps,type pos)
{
assert(ps);
Plus(ps);
assert(pos >= 0);
assert(pos <ps->size);
type begin = pos;
while (begin < ps->size-1)
{
ps->a[begin] = ps->a[begin + 1];
begin++;
}
ps->size--;
}
Test.c
#define _CRT_SECURE_NO_WARNINGS
#include "squential.h"
void Test1(void)
{
SL sl;
Init(&sl);
PushFront(&sl, 1);
PushFront(&sl, 2);
PushFront(&sl,3);
Print(&sl);
Destory(&sl);
}
void Test2(void)
{
/*SL sl;
Init(&sl); //打印表空
*/
SL sl;
Init(&sl);
PushFront(&sl, 1);
PushFront(&sl, 2);
PushFront(&sl, 3);
Print(&sl); //321
PopFront(&sl);
Print(&sl);//21
PushFront(&sl, 1);
PushFront(&sl, 2);
PushFront(&sl, 3);
Print(&sl);//32121
PopFront(&sl);
Print(&sl);//2121
Destory(&sl);
}
void Test3(void)
{
SL sl;
Init(&sl);
PushBack(&sl, 0);
Print(&sl);
PushFront(&sl, 1);
PushFront(&sl, 2);
PushFront(&sl, 3);
Print(&sl);
PushBack(&sl,4);
Destory(&sl);
}
void Test4(void)
{
SL sl;
Init(&sl);
PushFront(&sl, 1);
PushFront(&sl, 2);
PushFront(&sl, 3);
PopBack(&sl);
Print(&sl);
Destory(&sl);
}
void Test5(void)
{
SL sl;
Init(&sl);
Push(&sl,0, 1);
Push(&sl, 1,2);
Push(&sl, 2, 3);
Push(&sl, 3, 4);
Print(&sl);
Destory(&sl);
}
void Test6(void)
{
SL sl;
Init(&sl);
Push(&sl, 0, 1);
Push(&sl, 1, 2);
Push(&sl, 2, 3);
Push(&sl, 3, 4);
Delete(&sl, 2);
Print(&sl);
Destory(&sl);
}
int main()
{
//Test1();
//Test2();
//Test3();
//Test4();
//Test5();
Test6();
return 0;
}
当然我们还可以在里面丰富很多功能,比如删除重复的数字
//删除所有的x
//找到第一次出现x的位置
type Find(SL* ps,type x,type pos)
{
assert(ps);
for (type i = pos; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return - 1;
}
void del(SL* ps, type x)
{
assert(ps);
type i = Find(ps, x,0);
while (i != -1)
{
Delete(ps, i);
i=Find(ps, x,i+1);
}
}
感谢收看~