这是我的第一篇博客(内容为废话)
现在马上面临毕业的我,发现整理总结问题真的非常重要,刚刚开始学习数据结构,并且非科班出身的我,感觉得到压力非常大,所以开始学习完后在这进行回忆,复习学习。在这里要感谢传智播客的讲师传智扫地僧的课程。刚开始,肯定会有很多不好的地方,慢慢改变积少成多。特别喜欢一句话叫,十年饮冰,难凉热血。
什么是线性表?
首先说一说我理解的线性表,顾名思义,线性表就是用线串起来的表格呗,其实差不多一个意思,线性表就是零个或多个数据元素的有限序列,首先它是一个序列,也就是说,元素之间是有顺序的,必须是一个连着一个,不可能是一个连着好几个,其次他应该是有限个数的。其实计算机处理中所有的都是有限个数的,我们所说的无限的只存在与数学中。
数据结构之线性表顺序存储
线性表的顺序存储结构,指的就是用一段地址连续的存储单元依次储存线性表的数据元素。
废话不多说,直接上代码吧:
#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__
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);
#endif //__MY_SEQLIST_H__
上面代码为seqlist.h的头文件,需要完成的就对函数声明的实现,线性表顺序存储相当于一个在数组中存储数据,并且在内存中的顺序是连在一起的。要实现的功能为建立链表,摧毁链表,初始化链表(清空链表),求链表长度,求链表容量,在任意位置插入元素,得到任意位置元素,在任意位置删除元素。
功能实现
在功能实现之前因为存储到链表的数据类型不一样,所以要进行转换,要建立一个中间过程,我们用结构体来做,在结构体中嵌套一个一级指针。
typedef struct _tag_SeqList
{
int length;
int capacity;
unsigned int** node;
}TSeqList;
1、建立链表
SeqList* SeqList_Create(int capacity)
{
int ret = 0;
TSeqList* tmp = NULL;
tmp = (TSeqList*)malloc(sizeof(TSeqList));
//进行错误检查,如果没有成功分配内存,则建立链表失败
if(tmp == NULL){
ret = -1;
printf("func SeqList_Create err:%d\n",ret);
return NULL;
}
memset(tmp,0,siezeof(TSeqList));
//根据capacity分配空间
tmp->node = (unsigned int **)malloc(sizeof(unsigned int*)*capacity);
if(tmp->node == NULL){
ret = -1;
printf("func SeqList_Create err:malloc %d\n",ret);
return NULL;
}
tmp->length = 0;
tmp->capacity = capacity;
return tmp;
}
2、摧毁链表
void SeqList_Destroy(SeqList* list)
{
//摧毁链表,及将分配的内存回收
TSeqList* tlist = NULL;
if(tlist == NULL){
return;
}
tlist = (TSeqList*)list;
if(tlist->node != NULL){
free(tlist->node);
}
free(tlist);
}
3、清空链表
void SeqList_Clear(Seqlist* list)
{
//清空链表,相当于初始化链表,将所有参数初始化为开始值
TSeqList* tlsit = NULL;
if(tlist == NULL)
{
return;
}
tlist = (TSeqList*)list;
tlist->length = 0;
}
4、返回链表长度
int SeqList_Length(SeqList* list)
{
TSeqList* tlsit = NULL;
if(tlist == NULL)
{
return;
}
tlist = (TSeqList*)list;
return tlist->length;
}
5、返回链表实际容量
在这里要特别说明,链表的长度和容量不是一个东西,链表长度表示链表的实际存储的长度,capacity表示链表的容量。
int SeqList_Capacity(SeqList* list)
{
TSeqList* tlsit = NULL;
if(tlist == NULL)
{
return;
}
tlist = (TSeqList*)list;
return tlist->capacity;
}
6、在链表任意位置插入元素
int SeqList_Insert(SeqList* list,SeqListNode* node,int pos)
{
int ret = 0,i = 0;
TSeqList* tlist = NULL;
if(list == NULL || node == NUll ||pos<0){
ret = -1;
printf("func SeqList_Insert() err:%d \n",ret);
return ret;
}
tlist = (TSeqList*)list;
//判断插入元素后,链表是否会溢出
if(tlist->length >= tlist->capacity){
ret = -2;
printf("func SeqList_Insert() err:%d \n",ret);
return ret;
}
//容错修正,及插入的位置大于链表中数据的长度,在末尾插入元素
if(pos >= tlist->length){
pos = tlist->length;
}
//后移,插入新元素后,在插入位置后的元素要后移
if(i = tlist->length;i>pos;i--){
tlist->node[i] = tlist->node[i-1];
}
//插入元素
tlist->node[pos] = node;
tlist->length++;
return 0;
}
7、在链表任意位置得到元素
SeqListNode* SeqList_Get(SeqList* list,int pos)
{
int i = 0,ret = 0;
SeqListNode* tmp = 0;
TSeqList* tlist = NULL;
if(list == NULL || pos < 0){
ret = -1;
printf("func SeqList_Get() err:%d \n",ret);
return NULL;
}
tlist = (SeqList*)list;
tmp = (void*)tlist->node[pos];
return tmp;
}
8、在链表任意位置删除元素并返回删除的值
SeqListNode* SeqList_Del(SeqList* list,int pos)
{
int i = 0,ret = 0;
SeqListNode* tmp = 0;
TSeqList* tlist = NULL;
if(list == NULL || pos < 0){
ret = -1;
printf("func SeqList_Del() err:%d \n",ret);
return NULL;
}
tlist = (SeqLisst*)list;
tmp = (SeqListNode*)tlist->node[pos];
for(i = pos+1;i < tlist->length;i++){
tlist->node[i-1] = tlist->node[i];
}
tlist->length--;
return tmp;
}
至此所有的功能全部实现。
线性表顺序存储的优缺点
优点:
1、无需为表示表中元素之间的逻辑关系而增加额外的存储空间
2、可以快速的存取表中任意位置的元素
缺点:
1、插入和删除操作需要移动大量元素
2、当线性表长度变化较大时,难以确定存储空间的容量
3、造成存储空间的“碎片”