c语言实现单链表基础面试题

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用? 
2.从尾到头打印单链表 
3.删除一个无头单链表的非尾节点 
4.在无头单链表的一个节点前插入一个节点 
5.单链表实现约瑟夫环 
6.逆置/反转单链表 
7.单链表排序(冒泡排序&快速排序) 
8.合并两个有序链表,合并后依然有序 
9.查找单链表的中间节点,要求只能遍历一次链表 

10.查找单链表的倒数第k个节点,要求只能遍历一次链表

//从尾到头打印单链表
void ReversePrintf(ListNode* pList)//使用递归
{
	if (pList == NULL)
	{
		return;
	}
	else
	{
		ReversePrintf(pList->next);
	}
	printf("%d->", pList->data);
}

//删除一个无头单链表的非尾节点 
void EraseNoHead(ListNode* pos)//替换法
{
	ListNode* next = pos->next;
	DataType tmp = next->data;
	pos->data = tmp;
	pos->next = next->next;
	free(next);
}

//在无头单链表的一个节点前插入一个节点 
void InsertNoHead(ListNode* pos,DataType x)//替换法
{
	ListNode* tmp = BuyNode(x);
	ListNode* next = pos->next;
	pos->next = tmp;
	tmp->next = next;
	DataType data = pos->data;
	pos->data = tmp->data;
	tmp->data = data;
}

//单链表实现约瑟夫环 
ListNode* JosRing(ListNode*pList,int k)
{
	if (pList == NULL)
		return NULL;
	while (pList == pList->next)
	{
		int count = k;
		while (--count)
		{
			pList = pList->next;
		}
		ListNode* next = pList->next;
		pList->data= next->data;
		pList->next = next->next;
		free(next);
	}
	return pList;
}

//逆置/反转单链表 
ListNode* ReverseLinklist(ListNode** ppList)
{
	//1,链表为空或者只有一个节点
	//2,链表不为空
	if (*ppList == NULL || (*ppList)->next == NULL)
		return *ppList;
	else
	{
		ListNode* newplist = NULL;
		ListNode* atil = *ppList;
		while (atil)
		{
			ListNode* tmp = atil;
			atil = atil->next;//必须在这个位置,靠后的话,atil->next已经被改变,出错,接下
			tmp->next = newplist;//atil->next被赋值为newplist。
			newplist = tmp;
			/*atil->next = newplist;//这种是错的,留着提醒
			newplist = atil;
			atil = atil->next;*/
		}
		return newplist;
	}
}

//.单链表排序(冒泡排序&快速排序)
void BubbleSortLinklist(ListNode** ppList)
{
	if (*ppList == NULL || (*ppList)->next == NULL)
		return;
	else
	{
		ListNode* tail = NULL;//运用tail当作最后一个节点的next,也就是为空,然后在循环中每次向前
		while (tail != *ppList)//进一个节点
		{
			ListNode* cur = *ppList;
			ListNode* next = cur->next;
			int flag = 0;//优化
			while (next != tail)//	第一次tail为空,cur是空
			{
				if (cur->data > next->data)
				{
					DataType tmp = cur->data;
					cur->data = next->data;
					next->data = tmp;
					flag = 1;
				}
				next = next->next;
				cur = cur->next;
			}
			if (flag == 0)
				return;
			tail = cur;
		}
	}
}

//合并两个有序链表,合并后依然有序 
ListNode* CombineList(ListNode* list1,ListNode* list2)//先摘一个头,然后再继续尾插
{
	if (list1 == NULL)
	{
		return list2;
	}
	else if (list2 == NULL)
	{
		return list1;
	}
	else
	{
		ListNode* NewList = NULL;
		if (list1->data > list2->data)//摘头
		{
			NewList = list2;
			list2 = list2->next;
		}
		else
		{
			NewList = list1;
			list1 = list1->next;
		}
		ListNode* tail = NewList;
		while (list1&&list2)//尾插
		{
			if (list1->data > list2->data)
			{
				tail->next = list2;
				list2 = list2->next;
			}
			else
			{
				tail->next = list1;
				list1 = list1->next;
			}
			tail = tail->next;
		}
		if (list1 != NULL)
		{
			tail->next = list1;
		}
		else if (list2 != NULL)
		{
			tail->next = list2;
		}
		return NewList;
	}
}

//查找单链表的中间节点,要求只能遍历一次链表
ListNode* SearchMid(ListNode* pList)//通过快慢指针,一个走两步,一个走一步,当快指针到尾时,慢指针在中间位置
{
	ListNode* fast = pList;
	ListNode* slow = pList;
	//ListNode* prev = pList;//注释的内容是,当节点数为偶数时,中间结点有两个,定义一个变量,存储前一个节点的地址。
	while (fast && fast->next)//偶数节点找出来的是偶数个的后一个地址。
	{
		fast = fast->next->next;
		//prev = slow;
		slow = slow->next;
	}
	/*if (fast == NULL)
	{
		slow = prev;
	}*/
	return slow;
}

//查找单链表的倒数第k个节点,要求只能遍历一次链表
ListNode* FindTailkNode(ListNode *pList, DataType k)//快慢指针,快指针先走k位,然后与慢指针一起走,
{                                //快指针到尾时,慢指针在倒数第k个位置。
	if (pList == NULL)
	{
		return NULL;
	}
	ListNode* fast = pList;
	ListNode* slow = pList;
	while (k--)//(--k)也行,只不过是fast->next==NULL;
	{
		fast = fast->next;
	}
	while (fast != NULL)
	{
		fast = fast->next;
		slow = slow->next;
	}
	return slow;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值