静态链表删除操作,如图所示,我们要删除的元素是C
删除之后的结果为下图:
我们可以看到,删除也是分为两步进行的操作:
第一步为静态链表的游标传递,将删除所要删除的元素的游标传递给上一个元素的游标(如图所示,C的游标值3传递给了B的游标,删除C后,B的游标值变为了3)。
第二部为备用链表的游标传递,将删除后的元素回收到备用链表,即将数组第一个元素的游标传递给所删除元素的游标,并将数组第一个元素的游标变为所删除元素的下标(如图所示,这里删除C之后,将下标为0的元素的游标值6,传递给了下标为2的元素的游标值,并将自己的游标值改为了2)。
删除操作的实现代码:
/*删除在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=i; 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[MAX_SIZE-1].cur;
while(i)
{
i = L[i].cur;
j++;
}
return j;
}
静态链表优缺点总结:
1)优点:在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储结构中的插入和删除操作需要移动大量元素的缺点。
2)缺点:a.没有解决连续存储分配(数组)带来的表长难以确定的问题。 b.失去了顺序存储结构随机存取的特性。
总的来说,静态链表其实是为了给没有指针的编程语言设计的一种实现单链表功能的方法。尽管我们可以用单链表就不再用静态链表了,但这样的思考方式是非常巧妙的,应该理解其思想。
*腾讯面试题:快速找到未知长度单链表的中间结点
普通方法:首先遍历一遍单链表以确定单链表的长度L,然后再次从头结点出发循环L/2次找到单链表的中间节点。
高级方法:利用快慢指针。设置两个指针*fast和*slow都指向单链表的头结点,其中*fast的移动速度是*slow的两倍,当*fast指向末尾节点的时候,*slow正好就在中间节点了。这也是标尺的思想。
高级方法实现代码:
Status GetMidNode(LinkList L,ElemType *e)
{
LinkList search, mid;
mid = search = L;
while(search->next != NULL)
{
//search的移动速度是mid的两倍
if( search->next->next != NULL )
{
search = search->next->next;
mid = mid->next;
}
else
{
search = search->next;
}
}
*e = mid->next;
return OK;
}