1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
10.查找单链表的倒数第k个节点,要求只能遍历一次链表
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
10.查找单链表的倒数第k个节点,要求只能遍历一次链表
解答:
1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
顺序表:顺序表的地址空间是连续的,空间利用不充分。 查找速度快,便于大量元素的查找访问。但是不利于增、删。
链表: 链表的地址空间是不连续的,对于内存空间不会造成浪费。便于大量元素的指定位置增、删。但查找速度相对较慢。
(二者特性刚好互补。)
2.从尾到头打印单链表
//递归解决
void printfromback(ListNode* mylist)
{
//1没有节点或者只有一个节点
//2有多个节点
if(mylist != NULL)
{
return ;
}
else
{
printfromback(mylist->next);
printf("%d ",mylist->data);
}
}
3.删除一个无头单链表的非尾节点
//无头链表删除
//后一个节点覆盖前一个节点 在释放后一个节点
void deletnoheadlist(ListNode** pos )
{
ListNode* next;
assert(*pos);
assert((*pos)->next);
next = (*pos)->next;
(*pos)->data = next->data;
(*pos)->next = next->next ;
free(next);
}
4.在无头单链表的一个节点前插入一个节点
//无头链表插入
//在pos后面插入一个数,再交换两个节点的内容
void insertonheadlist(ListNode** pos, DataType input)
{
int tmp;
ListNode* cur = *pos;
ListNode* NewNode = BuyNode(input);
//插入新节点
NewNode->next = (*pos)->next;
(*pos)->next = NewNode;
//交换data
tmp = NewNode->data ;
NewNode->data = cur->data;
(*pos)->data = tmp;
}
5.单链表实现约瑟夫环
//约瑟夫环
//1把链表连起来
ListNode* JosephRing(ListNode** ppList, int k)
{
//1空链表
//2非空
ListNode* cur = *ppList;
if(*ppList == NULL)
{
return ;
}
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = (*ppList);
while((*ppList)->next != *ppList)
{
int loop = k;
while(--loop)
{
(*ppList) = (*ppList)->next;
}
//删除
(*ppList)->data = (*ppList)->next->data;
(*ppList)->next = (*ppList)->next->next;
}
return *ppList;
}
6.逆置/反转单链表
//链表逆置 头插法
//建一个新链表 在新链表上头插原来的节点元素
ListNode* ReverseList(ListNode** ppList)
{
//1链表为空 或者只有一个元素
//2链表不为空
ListNode* cur = *ppList;
ListNode* newlist=NULL ;
if((*ppList)->next == NULL || *ppList == NULL)
{
return ;
}
else
{
ListNode* tmp;
while(cur != NULL)
{
//摘节点
tmp = cur;
cur = cur->next;
//放节点
tmp->next =newlist;
newlist = tmp;
}
return newlist;
}
}
7.单链表排序(冒泡排序&快速排序)
//冒泡排序链表
void bubble_sotr_list(ListNode* pList)
{
//1链表为空或者只有一个节点
//2有多个节点
ListNode* cur = pList;
ListNode* nextnode = cur->next;
ListNode* stop = NULL;
DataType tmp;
if((pList) == NULL || nextnode == NULL)
{
return ;
}
else
{
while(stop != (pList)->next)
{
cur = pList;
nextnode = cur->next;
while(nextnode != stop)
{
if((cur->data) > (nextnode->data))
{
tmp = cur->data;
cur->data = nextnode->data;
nextnode->data = tmp;
}
cur =cur->next;
nextnode = nextnode->next;
}
stop = cur;
}
}
}
8.合并两个有序链表,合并后依然有序
//合并两个有序链表,合并后依然有序
ListNode* MergeList(ListNode* List1,ListNode* List2)
{
//1两个链表都为空
//2其中一个链表为空
//3两个链表都不为空
ListNode* Newlist = NULL;
ListNode* Newlisthead = NULL;
if(List1 == NULL && List2 == NULL)
{
return NULL;
}
else if (List1 != NULL && List2 == NULL)
{
return List1;
}
else if (List1 == NULL && List2 != NULL)
{
return List2;
}
else
{
//摘链表头
if(List1->data < List2->data)
{
Newlist = List1;
List1 = List1->next;
}
else
{
Newlist = List2;
List2 = List2->next;
}
Newlisthead = Newlist;
//往节点后面加节点
while(List1 !=NULL && List2 != NULL)
{
if(List1->data < List2->data)
{
Newlist->next = List1;
Newlist = Newlist->next;
List1 = List1->next;
}
else
{
Newlist->next = List2;
Newlist = Newlist->next;
List2 = List2->next;
}
}
//把剩余的链表链接上
if(List1 == NULL)
{
Newlist->next = List2;
}
if(List2 == NULL)
{
Newlist->next = List1;
}
return Newlisthead;
}
}
9.查找单链表的中间节点,要求只能遍历一次链表
//查找链表中心元素 (只能遍历一次)
//快慢指针
ListNode* find_list_mid(ListNode* pList)
{
//1为空
//2只有一个或者两个节点
//3有多个节点
ListNode* slow = pList;
ListNode* fast = pList;
if(pList == NULL)
{
return NULL ;
}
else if(pList->next == NULL || pList->next->next == NULL)
{
return pList;
}
else
{
while(fast && fast->next != NULL) //奇数偶数节点问题
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
}
10.查找单链表的倒数第k个节点,要求只能遍历一次链表
//找倒数第k个元素
ListNode* find_tail_k(ListNode* pList,int k)
{
//1链表为空
//2链表元素少于k
//3链表元素多余k
ListNode* slow = pList;
ListNode* fast = pList;
if(pList == NULL)
{
return NULL;
}
while(--k) //先走k步
{
fast = fast->next;
if(fast == NULL)
{
return NULL ;
}
}
while(fast->next != NULL) //一起走
{
slow = slow->next;
fast = fast->next;
}
return slow;
}