线性表的特点
单链表强调元素在逻辑上紧密相邻,所以首先想到用数组存储。但是普通数组有着无法克服的容量限制,在不知道输入有多少的情况下,很难确定出一个合适的容量。对此,一个较好的解决方案就是使用动态数组。首先用malloc申请一块拥有指定初始容量的内存,这块内存用作存储单链表元素,当录入的内容不断增加,以至于超出了初始容量时,就用realloc扩展内存容量,这样就做到了既不浪费内存,又可以让单链表容量随输入的增加而自适应大小。
特点:
- 线性表的顺序存储结构是一种随机存取的存储结构,因此只要确定了存储线性表的起始位置,线性表中任意数据元素都可以随机存取
- 线性表的插入或者删除操作,是一种牵一发而动全身的操作,插入元素需要将带插入位置后面的所有元素后移一位,删除元素反之
一 设置数据结构体
typedef int ElemType;
// 定义结构体
typedef struct SeqList_tag
{
ElemType * elem; //线性表的起始地址
int length; //线性表的长度
int size; //线性表现有的长度
}SeqList;
elem作为线性表的起始地址,内部存储的是线性表的第一个元素,可以根据这个地址,通过指针运算,找到后面的元素
二 初始化线性表
int InitList (SeqList * L)
{
// 1.1 分配一块内存
L->elem = (SeqList *) malloc (LIST_INIT_SIZE * sizeof (ElemType));
if (L->elem == NULL)
{
return -1;
}
// 1.2 结构体相关元素的初始化
L->length = 0;
L->size = LIST_INIT_SIZE;
return 0;
}
三 插入一个元素
// 6 在L中的第i个位置前插入新的元素e
int ListInsert (SeqList * L, int pos, int val)
{
ElemType * newbase;
ElemType * p;
ElemType * q;
// 6.1 首先判断链表L是否为空且插入的位置是否正确,如果错误,返回-1,结束程序
if ((pos < 1) || (pos > L->length + 1))
{
return -1;
}
// 6.2 判断当前是否还有空间存储新插入的元素,如果没有的话,使用realloc添加分配内存
if (L->length >= L->size)
{
newbase = (ElemType *) realloc (L->elem, (LISTINCREMENT + L->size) * sizeof (ElemType));
if (newbase == NULL)
{
return -1;
}
L->elem = newbase;
L->size += LISTINCREMENT;
}
// 6.3 插入元素
// 6.3.1 首先找到带插入元素的位置 ,直接进行指针插入运算
q = L->elem + pos - 1;
// 6.3.2 将pos位置的元素都向后移动一位,为插入的元素留下存储空间
for (p = L->elem + L->length - 1; p >= q; --p)
{
*(p - 1) = * p;
}
// 6.3.3 插入元素
*q = val;
// 6.3.4 总的长度 + 1
L->length += 1;
return 0;
}
四 删除一个元素
ElemType ListDelete (SeqList * L, int pos)
{
ElemType * p; // 存放待删除元素的地址
ElemType * q; // 存放线性表的最后一个元素的地址
ElemType val; // 保存待删除元素的值
if (pos < 1 || pos > L->length)
{
return 10086;
}
p = L->elem + pos - 1;
val = *p;
q = L->elem + L->length - 1;
for (; p <= q; p ++)
{
*(p - 1) = * p;
}
L->length -= 1;
return val;
}
查看某一个位置存放的元素内容
ElemType GetElem (SeqList * L, int pos)
{
if (pos < 1 || pos > L->length)
{
return -1;
}
return * (L->elem + pos - 1);
}
C语言中 -> 和 . 的区别
a->b 的含义是 (*a).b