静态链表
静态链表:
对静态链表进行初始化相当于初始化数组:
Status InitList(StaticLinkList space)
{
int i;
for( i=0; i<MAXSIZE-1;i++)
space[i].cur = i+1;
space[MAXSIZE-1].cur = 0;
return ok;
}
- 我们对数组的第一个和最后一个元素做特殊处理,他们的data不存放数据;
- 我们通常把未使用的数组元素称为备用链表;
- 数组的第一个元素,即下标为0的那个元素的cur就存放备用链表的第一个结点的下标;
- 数组的最后一个元素,即下标为MAXSIZE-1的cur则存放第一个有数值的元素的下标,相当于单链表中的头结点作用;
静态链表的插入操作:
// 首先是获得空间分量的下标:
int Malloc_SLL(StaticLinkList space)
{
int i = space[0].cur;
if( space[0].cur )
space[0].cur = space[i].cur;
// 把它的下一分量用来作为备用。
return i;
}
Status ListInsert( staticLinkList L, int i; ElemType e )
{
int j,k,l;
k = MAX_SIZE - 1;
if( i<1 || i>ListLength(L)+1 )
{
return ERROR;
}
j = Malloc_SLL(L);
if( j )
{
L[j].data = e;
for ( l=1; l<= i-1; l++)
{
k = L[k].cur;
}
L[j].cur = L[k].cur;
L[k].cur = j;
return ok;
}
return ERROR;
}
静态链表的删除操作
// 删除在L中的第i个数据元素
Status ListDelete(StaticLinkList L; int i)
{
int j,k;
if ( i<1 || i>ListLength(L) )
{
return ERROR;
}
k = MAX_SIZE - 1;
for( j=1; j <= i-1; j++ )
{
k = L[k].cur;
}
j = L[k].cur;
L[k].cur = L[j].cur;
Free_SLL(L,j);
return OK;
}
// 将下标为k的空间结点回收到备用链表
void Free_SLL(StaticLinkList space, int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
// 返回L中数据元素个数
int ListLength(StaticLinkList L)
{
int j = 0;
int i = L[MAXSIZE-1].cur;
while(i)
{
i = L(i).cur;
j++;
}
return j;
}
静态链表的优缺点
优点:
- 在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点;
缺点:
- 没有解决连续存储分配(数组)带来的表长难以确定的问题;
- 失去了顺序存储结构随机存取的特性;
单链表的小结:腾讯面试题
题目:快速找到未知长度单链表的中间节点。
- 第一种:首先遍历一遍单链表以确定单链表的长度L。然后再次从头结点出发循环L/2次找到单链表的中间结点。
- 第二种:利用快慢指针原理:设置两个指针search、mid都指向单链表的头结点。其中search的移动速度是mid的2倍。当*search指向末尾结点的时候,mid正好就在中间。
代码:
Status GetMidNode(LinkList L; Elemtype *e)
{
LinkList search, mid;
mid = search = L;
while (search->next != NULL)
{
if (search->next->next != NULL)
{
search = search->next->next;
mid = mid->next;
}
else
{
search = search->next;
}
}
*e = mid->data;
return OK;
}