线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串....
即顺序表为线性表的一种,
顺序表是一种物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数据上完成数据的增删查改。
顺序表一般分为
1.静态顺序表:使用定长数组存储元素
#defined N 7
typedef int SLDataType
typedef struct SeqList
{
SLDataType* data[N];
size_t size;
}
这时的数组是一个定长数组,长度为7。
其实这样的静态的顺序表缺点还是挺大的,除了简单,好像找不到什么优点,如果给德空间小了,就存不了数据了,如果给大了,就会显得浪费空间,所以为了弥补这样的缺点,于是就提出了动态顺序表的结构。何为动态顺序表,就是可以动态的分配空间,要多少给你分配多少,从而相对于静态的顺序表而言,很大程度上提升了大的灵活性。
typetef struct SeqList { SLDataType* data; size_t size; size_t capicity; }SeqList;
代码中给了一个数组的地址,然后给了存了数据个数的size,给了容量的大小,如果,size= capicity时,就进行扩容。
最后我们就可以写增删查改的结构函数了
接下来我们从创建动态顺序表到各种结构来解释我们今天的顺序表
首先第一步就是建立一个结构:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SeqListData;
typedef struct SeqList
{
SeqListData* data;
int size;
int capicity;
}seqList;
并且创建一个顺序表,并且对其进行初始化。
void test()
{
seqList sq;
SeqListInit(&sq);
SeqListDestroy(&sq);
}
因为我们要用realloc,在栈上申请内存,所以当程序结束后,我们要对在栈上申请的内存进行释放,要不然会发生内存泄漏现象。所以写了一个销毁内存的接口;
void SeqListDestroy(seqList*ps)
{
free(ps->data);
ps->data = NULL;
ps->capicity = 0;
ps->size = 0;
}
因为这是动态的,所以当空间不足时,要分配内存给它,所以也要写一个接口,来检查它的内存是不是满了;
接下来还有一个打印接口:
void SwqPrint(seqList*ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->data[i]);
}
printf("\n");
}
完成了一系列的辅助接口,接下来就是完成我们的增删查改,首先来下简单的,尾插:
void SeqListPushBack(seqList*ps, SeqListData x)
{
assert(ps);
CheckCapacity(ps);
ps->data[ps->size] = x;
ps->size++;
}
因为我们创建的是数组,所以尾插就比较方便,直接在后面加数据就行。
所以完成尾加之后加是尾删:
void SeqListPopBack(seqList*ps)
{
assert(ps);
assert(ps->size>0);
ps->size--;
}
所以尾删也很简单,就是使size减一,不访问这个数据就可以了。
#include"SeqList.h"
void test()
{
seqList sq;
SeqListInit(&sq);
SeqListPushBack(&sq, 1);//尾插如数据
SeqListPushBack(&sq, 2);
SeqListPushBack(&sq, 3);
SeqListPushBack(&sq, 4);
SwqPrint(&sq);
SeqListPopBack(&sq);
SwqPrint(&sq);
SeqListDestroy(&sq);
}
int main()
{
test();
return 0;
}
这是我们的测试代码,用以上的接口来玩成一部分的功能
接下来是头加和头删
void SeqListPushFront(seqList*ps, SeqListData x)
{
CheckCapacity(ps);
for (int i = ps->size - 1; i >=0; i--)
{
ps->data[i+1] = ps->data[i];
}
ps->data[0] = x;
ps->size++;
}
void SeqListPopFront(seqList*ps)
{
assert(ps->size > 0);
for (int i = 0; i < ps->size; i++)
{
ps->data[i] = ps->data[i + 1];
}
ps->size--;
}
接下来测试下新增的几个接口
void test()
{
seqList sq;
SeqListInit(&sq);
SeqListPushBack(&sq, 1);//尾插如数据
SeqListPushBack(&sq, 2);
SeqListPushBack(&sq, 3);
SeqListPushBack(&sq, 4);
SwqPrint(&sq);
SeqListPopBack(&sq);
SwqPrint(&sq);
SeqListPushFront(&sq,10);
SwqPrint(&sq);
SeqListPopFront(&sq);
SwqPrint(&sq);
SeqListDestroy(&sq);
}
int main()
{
test();
return 0;
}
最后我们来写一个寻找的接口,给一个数据,如果数组里有那就对应的小标,如果没有就打印找不到。
int SeqListFind(seqList*ps, SeqListData x)
{
int i = 0;
for ( i = 0; i < ps->size ; i++)
{
if (ps->data[i] == x)
{
return i;
}
}
if (i>ps->size)
{
printf("找不到\n");
}
return 0;
}
以上就是我们顺序表的基本操作增删查改