1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
- 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预分配。
它的优点 :
(1)方法简单,各种高级语言中都有数组,容易实现
(2)不用为表示节点间的逻辑关系而增加额外的存储开销。
(3) 顺序表具有按元素序号随机访问的特点
它的缺点:
(1)插入时需要将后面的元素逐个挪动比较麻烦
(2)动态存储比较麻烦,开大了浪费,开小了不够用 - 在链表中逻辑上相邻的数据元素,物理存储位置不一定相邻,它使用指针实现元素之间的逻辑关系。并且,链表的存储空间是动态分配的。
它的优点:插入删除方便
它的缺点:
(1) 需要占用额外的空间,来存储下一个节点的地址
(2)不能随机存取元素
应用场景:
在一次可开辟足够空间且节省空间则用顺序表
在需要多次增删查改则选用链表。
2.从尾到头打印链表:
思考方法:首先我们需要找到最后一个节点,且还能回到上一个节点,我们可以想到递归,我们传头结点”pList”给函数,函数判断节点是否为NULL,若为NULL,则打印NULL,反之我们继续调用函数,传pList->next,则实现了:先找到最后一个节点,并在函数返回后找到上个节点的值pList->data;
void PrintHeadtoTail(ListNode *pList)//从尾到头打印链表
{
if(pList == NULL)
{
printf("NULL");
return;
}
PrintHeadtoTail(pList->next);//传pList->next
//函数返回时不会改变plist的值
printf("<-%d",pList->data); //打印pList->data
}
3.删除一个无头链表的非尾节点
函数名: void ErasenonTail(ListNode *pos);
1.当看到这个问题的时候,我想这么简单的问题,我想到的代码是:
void ErasenonTail(ListNode *pos)
{
ListNode *pavi = pos;
pos = pos->next;
free(pavi);
}
2.但运行之后,我发现程序崩溃了,我就很纳闷。我就一步一步的调试发了许多很可笑的问题:
void ErasenonTail(ListNode *pos)
//这里的pos虽然值和链表节点的值相同,但修改pos链表不会改变
{
ListNode *pavi = pos;
pos = pos->next;//pos是值传递
free(pavi);
pavi = NULL;//这里就更可笑了,函数内部定义的值置空
}
3.经过这一次的教训,我发现不能小看任何一道题,所以我利用画图得到了一个办法
代码:
void ErasenonTail(ListNode *pos)//
{
assert(pos);
ListNode *tail = pos->next;
pos->data = tail->data; //对指针的引用改变指针所指向空间的值
pos->next = tail->next;
free(tail);
}
4. 在无头单链表的一个节点前插入一个节点
这个题和上一个题的方法一样,在链表节点后加一个节点简单,再交换这个节点和新添加的节点的数据;
void InsertnonTail(ListNode* pos, DataType x)//无头链表节点前添加
{
assert(pos);
ListNode *pavi = NULL;
Compatibo(&pavi);
pavi->data = pos->data;
pos->data = x;
pavi->next = pos->next;
pos->next = pavi;
}
5. 单链表实现约瑟夫环
//头结点 ppList ,开始的人数 n, 每次数的数m
void Josephus(ListNode **ppList,int n, int m)
{
assert(ppList);
ListNode *ret = NULL;
ListNode *tail = NULL;
int i = 0;
for(i=1; i<=n; i++)
{
PushBack(ppList, i);
}
ret = Find(*ppList,n);
ret->next = *ppList;//创建了一个循环链表
while(*ppList != (*ppList)->next)
{
ret = *ppList;
for(i=0;i<m-1; i++)//找出要删除的节点
{
ret = ret->next;
}
EraseCrc(ppList, ret);//删除节点(注意头结点不能变)
//在删除头一个节点的时候,应利用无头节点删除的方法
}
printf("%d\n",(*ppList)->data);
}