一。线性表
线性表
(
linear list
)
是
n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串
...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
二。顺序表
2.1 概念
顺序表是用一段
物理地址连续
的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组 上完成数据的增删查改。
顺序表一般可以分为:
1. 静态顺序表:使用定长数组存储元素。
#define N 7
typedef int SLDataType;
typedef struct SList{
SLDataType array[N];
size_t size;
}SList;
2. 动态顺序表:使用动态开辟的数组存储
typedef int SLDataType;
typedef struct SList{
SLDataType *array;
size_t size;
size_t capacity;
}SList;
2.2 实现
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致空间的空余或者不足。所以基本都是使用动态顺序表,根据需要来动态的分配空间大小,下面实现动态顺序表
1.头文件
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int SLDateType;
typedef struct SeqList
{
SLDateType* array;
size_t size;
size_t capacity; // unsigned int
}SeqList;
// 对数据的管理:增删查改
void SeqListInit(SeqList* ps,int initCapacity );//初始化
void SeqListDestory(SeqList* ps);//顺序表销毁
void SeqListPrint(SeqList* ps);//打印顺序表
void CheckCapacity(SeqList* ps);//扩容
void SeqListPushBack(SeqList* ps, SLDateType data);//往顺序表尾插一个元素
void SeqListPushFront(SeqList* ps, SLDateType data);//头插
void SeqListPopFront(SeqList* ps);//头删
void SeqListPopBack(SeqList* ps);//删除最后一个元素
int SeqListSize(SeqList* ps);//返回有效元素个数
int SeqListCapacity(SeqList* ps);//获取容量
int SeqListEmpty(SeqList* ps);//检测顺序表是否为空
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType data);
// 顺序表在pos位置插入data
void SeqListInsert(SeqList* ps, size_t pos, SLDateType data);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos);
2.函数功能实现
void SeqListInit(SeqList* ps, SLDateType initCapacity) { //初始化
assert(ps);
initCapacity = initCapacity <= 0 ? 3 : initCapacity;
ps->array = (SLDateType*)malloc(sizeof(SLDateType) * initCapacity);
if (NULL == ps->array) {
assert(0);
return;
}
ps->capacity = initCapacity;
ps->size = 0;
}
void SeqListDestory(SeqList* ps) { //顺序表销毁
assert(ps);
if (ps->array) {
free(ps->array);
ps->array = NULL;
ps->capacity = 0;
ps->size = 0;
}
}
void SeqListPrint(SeqList* ps) { //打印顺序表
assert(ps);
for (int i = 0; i < ps->size; i++) {
printf("%d ", ps->array[i]);
}
printf("\n");
}
void SeqListPushBack(SeqList* ps, SLDateType data) { //往顺序表尾插一个元素
assert(ps);
//扩容
CheckCapacity(ps);
ps->array[ps->size] = data;
ps->size++;
}
void SeqListPushFront(SeqList* ps, SLDateType data) { //头插
assert(ps);
//检测空间是否足够
CheckCapacity(ps);
for (int pos = ps->size - 1; pos >= 0; pos--) {
ps->array[pos + 1] = ps->array[pos];
}
ps->array[0] = data;
ps->size++;
}
void SeqListPopFront(SeqList* ps) { //头删
assert(ps);
if (SeqListEmpty(ps)) {
return;
}
for (int pos = 1; pos < ps->size; pos++) {
ps->array[pos - 1] = ps->array[pos];
}
ps->size--;
}
void SeqListPopBack(SeqList* ps) { //删除最后一个元素
assert(ps);
if (SeqListEmpty(ps)) {
return;
}
ps->size--;
}
int SeqListSize(SeqList* ps) { //返回有效元素个数
return ps->size;
}
int SeqListCapacity(SeqList* ps) { //获取容量
return ps->capacity;
}
int SeqListEmpty(SeqList* ps) { //检测顺序表是否为空
return ps->size == 0;
}
void CheckCapacity(SeqList* ps) {
assert(ps);
if (ps->size == ps->capacity) {
int newCapacity = ps->capacity * 2;
/*int* temp = (int*)malloc(sizeof(int) * newCapacity);
if (NULL==temp) {
assert(0);
return;
}
memcpy(temp, ps->array, ps->size * sizeof(int));
free(ps->array);
ps->array = temp;
ps->capacity = newCapacity;*/
ps->array = (int *)realloc(ps->array, sizeof(int) * newCapacity);
if (NULL == ps->array) {
assert(0);
return;
}
ps->capacity = newCapacity;
}
}
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType data) {
for (int i = 0; i < ps->size;i++) {
if (ps->array[i] == data) {
return 1;
break;
}
}
return -1;
}
// 顺序表在pos位置插入data
void SeqListInsert(SeqList* ps, size_t pos, SLDateType data) {
assert(ps);
if (pos<0||pos>ps->size) {
printf("pos位置非法!");
return;
}
//检测空间是否足够
CheckCapacity(ps);
for (int i=ps->size-1; i>=pos; i--) {
ps->array[i+1] = ps->array[i];
}
ps->array[pos] = data;
ps->size++;
}
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, size_t pos) {
assert(ps);
if (SeqListEmpty(ps)) {
return;
}
if (pos<0 || pos>=ps->size) {
printf("pos位置非法!");
return;
}
for (int i=pos+1; i < ps->size; i++) {
ps->array[i-1] = ps->array[i];
}
ps->size--;
}
2.3总结
顺序表优点:
1.无需为表示表中元素之间的逻辑关系而增加额外的存储空间
2.存取速度高效,通过下标来直接存储
顺序表缺点:
1.插入删除操作需要移动大量元素
2.当线性表长度变化较大时,难以确定存储空间的容量
(个人见解,还有许多方面)。