1.线性表
线性表顾名思义是线性存储的,数组就是一个典型的线性表,线性表在逻辑结构上是线性的但是物理结构上不一定是连续的,通常以数组或链式结构储存
2.顺序表
这篇文章主要介绍的是顺序表,顺序表分为两种,
- 一种是静态的内存大小固定存满了就无法在增加了我们就是静态顺序表
例如:
//静态顺序表
#define N 100
typedef int SLDateType;
typedef struct SeqList
{
SLDateType array[N]; //元素数组
int size; //存元素个数
}SL;
- 还有一种是通过动态申请内存链表增加内存叶增加的我们叫它动态顺序表
例如:
//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a; //元素数组
int size; //存元素个数
int capacity; //存空间大小
}SL;
2.1代码结构设计
第一种顺序表由于无法扩容,我们直接选择第二种来完成
如下则是我们顺序表的结构体和要完成的功能模块,一般我们写在一个头文件中
- 这里有个特殊的点我们 typedef 重定义了int 这样当我们需要存储别的类型的数据就可以直接在typedef 这里改不用把每个地方的 int 都改一遍了
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//动态顺序表
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a; //元素数组
int size; //存元素个数
int capacity; //存空间大小
}SL;
//初始化顺序表
void SLInit(SL* pc);
//销毁顺序表
void SLDestroy(SL* pc);
//打印顺序表
void SLPrint(SL* pc);
//检查并扩容
void SLExpansion(SL* pc);
//尾插
void SLPushBack(SL* pc,SLDataType x);
//尾删
void SLPopBack(SL* pc);
//头插
void SLPushFront(SL* pc,SLDataType x);
//头删
void SLPopFront(SL* pc);
//在pos位置插入x
void SLInsert(SL* pc, int pos, SLDataType x);
//删除pos位置的值
void SLErase(SL* pc, int pos);
SLDataType* a; //元素数组
int size; //存元素个数
int capacity; //存空间大小
这是结构体的三个值分别是存顺序表头指针,顺序表元素个数,和顺序表现有空间大小的,我们一般通过指针加size访问每个元素,和数组类似。
2.2顺序表功能完成
以下是关于顺序表的功能函数,主要是顺序表的创建,内存的申请和增删查改这些功能
值得注意的是在数据结构中边界问题非常重要,写代码多思考画图把边界想清楚这样可以大大的增加效率
//扩容
void SLExpansion(SL* pc)
{
assert(pc);
if (pc->size == pc->capacity)
{
SLDataType* tmp = (SLDataType*)realloc(pc->a, pc->capacity * 2 * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc del");
exit(-1);
}
pc->capacity *= 2;
pc->a = tmp;
tmp = NULL;
}
}
//创建链表
void SLInit(SL* pc)
{
assert(pc);
SLDataType* tmp = (SLDataType*)malloc(4 * sizeof(SLDataType));
if (tmp == NULL)
{
perror("malloc del");
exit(-1);
}
pc->a = tmp;
pc->size = 0;
pc->capacity = 4;
}
//初始化链表
void SLDestroy(SL* pc)
{
assert(pc);
free(pc->a);
pc->a = NULL;
pc->size = pc->capacity = 0;
}
//尾插
void SLPushBack(SL* pc, SLDataType x)
{
//满了扩容
//SLExpansion(pc);
尾插
//pc->a[pc->size] = x;
//pc->size++;
assert(pc);
SLInsert(pc, pc->size + 1, x);
}
//打印链表
void SLPrint(SL* pc)
{
assert(pc);
for (int i = 0; i < pc->size; i++)
{
printf("%d ", pc->a[i]);
}
printf("\n");
}
//尾删
void SLPopBack(SL* pc)
{
assert(pc);
assert(pc->size > 0);
//pc->size--;
SLErase(pc, pc->size);
}
//头插
void SLPushFront(SL* pc, SLDataType x)
{
assert(pc);
检查内存
//SLExpansion(pc);
元素后移
//for (int i = pc->size; i > 0; i--)
//{
// pc->a[i] = pc->a[i - 1];
//}
//pc->a[0] = x;
//pc->size++;
SLInsert(pc, 1 , x);
}
//头删
void SLPopFront(SL* pc)
{
assert(pc);
assert(pc->size > 0);
//for (int i = 0; i < pc->size ; i++)
//{
// pc->a[i] = pc->a[i + 1];
//}
//pc->size--;
SLErase(pc, 1);
}
//在pos位置插入x
void SLInsert(SL* pc, int pos, SLDataType x)
{
assert(pc);
//检查扩容
SLExpansion(pc);
assert(pos >= 0 && pos <= pc->size+1);
for (int i = pc->size; i > pos-1; i--)
{
pc->a[i] = pc->a[i - 1];
}
pc->a[pos - 1] = x;
pc->size++;
}
//删除pos位置的值
void SLErase(SL* pc, int pos)
{
assert(pc);
if (pos > pc->size || pos < 1)
{
printf("中间删错误\n");
return ;
}
for (int i = pos-1; i < pc->size; i++)
{
pc->a[i] = pc->a[i + 1];
}
pc->size--;
}
在数据结构中顺序表相对简单,以上就是我对顺序表的部分理解如果有不对的地方欢迎指出。