1.比较顺序表和链表的优缺点,说说他们正在什么场景下使用?
答:
对于顺序表,无论是动态还是静态,他们有都会死连续的存储空间,在读取时间效率上比较短,但在插入和删除时会比较麻烦,需要不断的遍历去找到尾节点。
对于链表,因为是链式存储。因此在需要的时候我们才在堆上进行开辟空间,链表对于插入删除比较简单,但是遍历需要多次跳转。
对于空间申请方式:
顺序表,空间开辟是在顺序表空间已满时开辟,开辟次数较多时会出现较大的空间浪费。
对于链表,空间是针对单个节点的,不存在多余的空间浪费。并且在碎片空间池的机制下,有效利用碎片空间。
所以,顺序表一般用于查找遍历操作比较频繁的情况下进行使用,链表则针对于数据删除修改比较频繁的数据使用。
2.从未到头打印单链表
void PrintNodeTailToHead(ListNode *head)
{
if (head)
{
while (head->next)
{
PrintNodeTailToHead(head->next);
}
}
printf("%d->",head->data);
}
3.删除一个无头单链表的非尾节点
void DelNoTail(ListNode*plist)
{
ListNode*del = plist->next;
plist->data = del->data;
plist->next = del->next;
free(plist);
plist = NULL;
}
4.在无头单链表的一个节点前程插入一个节点
void Insert(ListNode** ppList, ListNode* pos, DataType x)
{
if ((*ppList) == NULL)
{
*ppList = BuyNode(x);
}
else
{
ListNode *cur = BuyNode(x);
cur->next = pos->next;
pos->next = cur;
}
}
5.单链表实现约瑟夫环
DataType JLink(ListNode**pplist)
{
ListNode *cur = *pplist;
while ((*pplist)->next)
{
ListNode *del = *pplist;
del = (*pplist)->next->next->next;
*pplist = del;
free(del);
del = NULL;
}
return (*pplist)->data;
}
6.逆置/ 反转单链表
void _Reversre(ListNode*plist)//递归
{
ListNode *cur = plist;
ListNode *prev = plist;
while (cur->next)
{
prev = cur;
cur = cur->next;
}
cur->next = prev;
}
void reverse(ListNode**listhead)//非递归
{
if ((NULL == (*listhead)) || (NULL == ((*listhead)->next)))
return; //边界检测
ListNode* ppre = *listhead; //先前指针
ListNode* pcur = ppre->next; //当前指针
ListNode* pnext = NULL; //后继指针
while (pcur != NULL)
{
pnext = pcur->next;
pcur->next = ppre;
ppre = pcur;
pcur = pnext;
}
(*listhead)->next = NULL;
(*listhead) = ppre; //记录下新的头结点
}
7.单链表排序(冒泡排序)
void sort(ListNode*plist)
{
//冒泡
ListNode *max=plist;
DataType tmp;
while (max->next)
{
if ((max->data) < plist->data)
{
tmp = max->data;
max->data = plist->data;
plist->data = tmp;
}
else
plist = plist->next;
if (plist->next == NULL)
{
max = max->next;
}
}
}
8.合并两个有序链表,合并后依然有序
ListNode Merge(ListNode* head1, ListNode* head2)
{
ListNode* newhead = NULL;
if (head1->data < head2->data)
{
newhead = head1;
head1 = head1->next;
newhead->next = Merge(head1, head2);
}
if (head1->data>head2->data)
{
newhead = head2;
newhead->next = Merge(head1, head2->next);
}
}
9.查找单链表的中间节点,要求只遍历一遍
ListNode FindMid(ListNode*plist)
{
ListNode *slow = plist;
ListNode *fast = plist;
while (fast)
{
fast = fast->next->next;
slow = slow->next;
}
return *slow;
}
10.查找单链表的倒数第K个节点,要求只遍历一遍
ListNode FindReNum(ListNode*plist, int k)
{
ListNode*fast = plist;
ListNode*slow = plist;
while (k--)
{
fast=fast->next;
}
while (fast)
{
fast = fast->next;
slow = slow->next;
}
return *slow;