线性表的顺序存储
1.基本概念
2.设计和实现
2.1 插入元素算法
- 判断线性表是否合法
- 判断插入位置是否合法
- 把最后一个元素到插入位置的元素后移一个位置
- 将新元素插入
- 线性表长度加1
2.2 获取元素操作
- 判断线性表是否合法
- 判断位置是否合法
- 直接通过数组下标的方式获取元素
2.3 删除元素算法
- 判断线性表是否合法
- 判断删除位置是否合法
- 将元素取出
- 将删除位置后的元素分别向前移动一个位置
- 线性表长度减1
2.4 具体代码:
- 头文件:
#pragma
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
/*数据类型的封装--使用void类型*/
typedef void SeqList;
typedef void SeqListNode;//接受任意类型的数据元素,
//存放的是具体数据元素的首地址,
//不是直接存放数据元素
/*顺序存储各个函数*/
SeqList* SeqList_Create(int capacity);
void SeqList_Destroy(SeqList* list);
void SeqList_Clear(SeqList* list);
int SeqList_Length(SeqList* list);
int SeqList_Capacity(SeqList* list);
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
SeqListNode* SeqList_Get(SeqList* list, int pos);
SeqListNode* SeqList_Delete(SeqList* list, int pos);
- 实现文件
#include "seqlist.h"
/*表头数据结构*/
typedef struct _MyStruct
{
int length;//当前实际长度
int capacity;//容量
unsigned int * node;//线性表的起始位置,线性表里的每一个节点存放的是地址值,
//该地址是每个数据元素的起始地址,类似于Linux内核里面的链表思想
}TSeqList;
/*创建线性表*/
SeqList* SeqList_Create(int capacity)
{
TSeqList * tmp = NULL;//表头
tmp = (TSeqList*)malloc(sizeof(TSeqList));//为表头分配内存
if (NULL == tmp)
{
printf("Sorry!\n");
return NULL;
}
memset(tmp, 0, sizeof(TSeqList));//初始化表头
/*根据容量分配内存*/
tmp->node = (unsigned int *)malloc(sizeof(unsigned int )*capacity);
if (tmp->node == NULL)
{
printf("sorry!!\n");
return NULL;
}
/*初始化容量和长度*/
tmp->capacity = capacity;
tmp->length = 0;
/*返回表头*/
return tmp;
}
/*销毁线性表*/
void SeqList_Destroy(SeqList* list)
{
TSeqList * tmp = NULL;
/*合法性检测*/
if (list == NULL)
{
return ;
}
tmp = (TSeqList*)list;
/*先释放线性表*/
if (tmp->node != NULL)
{
free(tmp->node);
}
/*再释放表头*/
free(tmp);
return ;
}
/*清空线性表*/
void SeqList_Clear(SeqList* list)
{
TSeqList * tmp = NULL;
if (list == NULL)
{
return ;
}
tmp = (TSeqList*)list;
tmp->length = 0;//清空长度即可
return ;
}
/*获取线性表长度*/
int SeqList_Length(SeqList* list)
{
TSeqList * tmp = NULL;
if (list == NULL)
{
return -1;
}
tmp = (TSeqList*)list;
return tmp->length;
}
/*获取容量*/
int SeqList_Capacity(SeqList* list)
{
TSeqList * tmp = NULL;
if (list == NULL)
{
return -1;
}
tmp = (TSeqList*)list;
return tmp->capacity;
}
/*插入元素:把数据元素的首地址放进线性表的节点*/
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)
{
TSeqList * tmp = NULL;
int i = 0;
/*合法性判断*/
if (list == NULL || node == NULL || pos < 0)
{
printf("argv is error\n");
return -1;
}
tmp = (TSeqList*)list;
/*线性表是否已满*/
if (tmp->capacity <= tmp->length)
{
printf("is full\n");
return -2;
}
/*给出的目标位置是否合理*/
if (pos >= tmp->length)
{
pos = tmp->length;//容错纠正
}
/*元素后移*/
for (i = tmp->length; i > pos;i--)
{
tmp->node[i] = tmp->node[i - 1];
}
tmp->node[i] = (unsigned int)node;//将数据元素首地址直接存入线性表节点中
tmp->length++;//长度修改
return 1;
}
/*获取指定位置的元素*/
SeqListNode* SeqList_Get(SeqList* list, int pos)
{
TSeqList * tmp = NULL;
if (list == NULL || pos < 0)
{
printf("argv is error\n");
return NULL;
}
tmp = (TSeqList*)list;
return (void *)(tmp->node[pos]);//返回数据元素的首地址
}
/*从线性表删除指定位置的数据元素*/
SeqListNode* SeqList_Delete(SeqList* list, int pos)
{
TSeqList * tmp = NULL;
SeqListNode * ret = NULL;
int i = 0;
if (list == NULL || pos < 0)
{
printf("argv is error\n");
return NULL;
}
tmp = (TSeqList*)list;
/*容错纠正*/
if (pos >= tmp->length)
{
pos = tmp->length;
}
/*获取要删除的数据元素的首地址*/
ret = (void*)(tmp->node[pos]);
/*元素前移*/
for (i = pos + 1; i < tmp->length; i++)
{
tmp->node[i - 1] = tmp->node[i];
}
tmp->length--;//修改长度
return ret;//返回被删除的数据元素首地址
}
- 测试文件
#include "seqlist.h"
typedef struct _Teacher
{
int age;
char name[64];
}Teacher;
void main()
{
int ret = 0, i = 0;
SeqList* list = NULL;
Teacher t1, t2, t3, t4, t5;
t1.age = 31;
t2.age = 32;
t3.age = 33;
t4.age = 34;
t5.age = 35;
list = SeqList_Create(10);
if (list == NULL)
{
printf("func SeqList_Create() ret :%d \n", ret);
return;
}
ret = SeqList_Insert(list, (SeqListNode*)&t1, 0); //头插法
ret = SeqList_Insert(list, (SeqListNode*)&t2, 0); //头插法
ret = SeqList_Insert(list, (SeqListNode*)&t3, 0); //头插法
ret = SeqList_Insert(list, (SeqListNode*)&t4, 0); //头插法
ret = SeqList_Insert(list, (SeqListNode*)&t5, 0); //头插法
//遍历
for (i = 0; i<SeqList_Length(list); i++)
{
Teacher* tmp = (Teacher *)SeqList_Get(list, i);
if (tmp == NULL)
{
return;
}
printf("tmp->age:%d ", tmp->age);
}
int var = 190;//同时插入Teacher和int类型的数据
ret = SeqList_Insert(list, (SeqListNode*)&var, 0); //再次证明该顺序表可以插入任意类型的数据元素
printf("%d\n%d\n",(*(int *)SeqList_Get(list, 0)) + 1,SeqList_Length(list));
//删除链表中的节点
while (SeqList_Length(list) > 0)
{
SeqList_Delete(list, 0);
}
SeqList_Destroy(list);
system("pause");
return;
}
3. 优缺点
优点:
- 无需为线性表中的逻辑关系增加额外的空间
- 可以快速的获取表中合法位置的元素
缺点:
- 插入和删除操作需要移动大量元素
- 当线性表长度变化较大时难以确定存储空间的容量