单链表基础面试题

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
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;
}






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值