线性表:线性表有顺序表示和链式表示两种。
线性表的顺序表示:
因为顺序表是连续的存储地址,所以在初始化顺序线性表的时候就会分配好一个固定值的内存。如果在向线性表插值的过程中出现初始分配内存不足,则调用reallac重新分配内存,顺序表起始地址不变。所以在destroy的时候,只需要将顺序表的起始指针free掉就ok。
#define SQLIST_INIT_SIZE 5
struct SqList
{
int *a; //数据地址
int length; //当前长度
int listSize;//线性表总容量
SqList()
{
a = NULL;
length = 0;
listSize = 0;
}
};
bool InitSqList(SqList &list)
{
list.a = (int *)malloc(sizeof(SqList)*SQLIST_INIT_SIZE);
if(!list.a)
return false;
list.length = 0;
list.listSize = SQLIST_INIT_SIZE;
return true;
}
//线性表的销毁
bool DestroySqList(SqList &list)
{
if(list.a)
{
free(list.a);
list.a = NULL;
list.length = 0;
list.listSize = 0;
}
else
{
printf("list is not init!\n");
return false;
}
return true;
}
//线性表插入 第i个位置插入a
bool ListInsert(SqList &list,int i,int a)
{
if(list.a)
{
if(list.length>=list.listSize) //如果超出链表容量
{
list.a = (int *)realloc(list.a,list.listSize + sizeof(SqList)*SQLIST_INIT_SIZE);
list.listSize += SQLIST_INIT_SIZE;
}
if(i>list.length ) //如果所要插入的位置超过链表长度
{
*(list.a+list.length ) = a;
}
else
{
int j = list.length ;
for(;j>=i;--j)
{
*(list.a + j) = *(list.a + j -1); //要在第i位插入的话,那么length - i + 1 个元素要向后移动一位
}
*(list.a + j) = a;
}
++list.length;
return true;
}
else
{
printf("list is not init!\n");
return false;
}
}
//遍历
bool TraversalSqList(const SqList &list)
{
if(list.a)
{
printf("list has :");
for(int i = 0;i < list.length;++i)
{
printf("%d ",*(list.a + i));
}
printf("\n");
return true;
}
else
{
printf("list is not init!\n");
return false;
}
}
bool ClearList(SqList &list)
{
if(list.a)
{
*list.a = 0;
list.length = 0;
return true;
}
else
{
printf("list is not init!\n");
return false;
}
}
int ListLength(const SqList &list)
{
return list.length;
}
线性表的链式表示:
链表的内存分配方式与顺序表的不同,链表是在每次插入一个结点的时候分配一个节点的内存,所以每次delete一个元素的时候就要把这个元素的内存释放掉。
链表中必须有一个头指针!如果没有头指针,将不能知道链表存放在哪里,是从哪里开始的。有时候为了方便会为链表的第一个结点前加一个头结点,头结点中的数据部分可以不存储数据(初始值),而指针域必须指向下一个结点的位置。
线性表如果要查找第i个元素的数据的话,必须要从头指针出发寻找,因此,单链表是非随机存取的存储结构。
栈:
栈也可以用线性表是和链式表示。分配内存的方式与线性表的顺序表示和链式表示分配内存的方法类似。顺序表示:先分配好一定量的内存。而链式可以不用