线性表:是n个具有相同特性的数据元素的有限序列。
常见线性表:顺序表,链表,栈,队列,字符串......
物理结构非线性意味着地址不一定是连续的。
顺序表(SeqList)是物理地址连续的,用数组存储,数据是依次存储的。
静态数据表
typedef int SLDataType;//重定义int型
#define N 10
struct SeqList
{
SLDataType a[N];
int size;
}
动态数据表:可改变按需申请
typedef int SLDataType;
typedef struct SeqList
{
SLDataType*a;
int size;//有效数据个数
int capacity;//空间容量,空间容量=有效数据个数时扩容
}SL;
为什么不用柔性数组?size和capacity不需要处于同块一个空间
动态链表增删查改内码实现
头文件:库函数,结构体,重定义数据类型,增删查改函数
#pragma once
#include<stdio.h>
#include<stdlib.h>
//定义顺序表的数据类型
typedef int SLDatatype;
//定义数据类型结构体
typedef struct SeqList
{
SLDatatype* key;//空间指针
SLDatatype size;//空间下标
SLDatatype capacity;//空间容量
}SL;
//初始化
void InitSL(SL* p);
// 打印
void PrintSL(SL* p);
//尾增加
void SLAddback(SL* p, SLDatatype add);
//尾删除
void SLsubback(SL* p);
//扩容
SLDatatype* Addspace(SL* p);
测试源文件:初始化,增删查改等操作。
#include"SeqList.h"
int main()
{
SL s;//创建变量
InitSL(&s);//初始化
SLAddback(&s, 1);//加1
SLAddback(&s, 2);//加2
SLAddback(&s, 3);
PrintSL(&s);//打印
printf("\n");//分行
SLAddback(&s, 4);
PrintSL(&s);
printf("\n");
SLsubback(&s);
SLsubback(&s);
PrintSL(&s);
free(s.key);
s.key = NULL;
return 0;
}
链表功能实现源文件
#include"SeqList.h"
//初始化代码
//开辟一个能存放3个int的空间
void InitSL(SL* p)
{
p->size = 0;
p->capacity = 3;
p->key = (SLDatatype*)malloc(sizeof(SLDatatype) * p->capacity);
}
//打印代码
void PrintSL(SL* p)
{
for (int i = 0; i <p->size; i++)
{
printf("%d ", p->key[i]);
}
}
//扩容代码
SLDatatype* Addspace(SL* p)
{
SLDatatype* tmp = realloc(p->key, sizeof(SLDatatype) * (p->capacity + 2));
if (tmp == NULL)
return NULL;
return tmp;
}
//尾部添加代码
void SLAddback(SL* p,SLDatatype add)
{
if (p->size + 1 == p->capacity)
{
p->key = Addspace(p);
}
p->key[p->size++] = add;
}
//尾部减少代码
void SLsubback(SL* p)
{
if (p->size == 0)
return;
p->size--;
}
易错点
size值表示将要放入数据的下标,因此打印时次数是size-1
扩容代码中realloc的大小不是capacity而是capacity*sizeof(SLDatatype)。
记得判定返回指针是否为空,且要把返回指针赋给原来的指针。
减少数据是只用改变size,应为打印的循环次数只和size有关。
顺序表是结构体,定义int*指针。
顺序表缺点
中间头部插入数据,需要挪动数据,效率低下。
空间不够,扩容,扩容有一定消耗,其次有一定空间浪费。