单链表常见面试题(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yc1515707718/article/details/80406969

1.从尾到头打印单链表

通过递归找到最后一个节点输出,然后通过条件判断层层返回输出。

void ReversePrint(Slist* head)	//从尾到头输出单链表
{
	if (head == NULL)
	{
		return;
	}
	Slist* cur = head;
	if (cur->next == NULL)		//只有一个节点
	{
		printf("%d ", cur->data);
		return;
	}
	ReversePrint(cur->next);
	printf("%d ", cur->data);
	
}

2.删除一个无头单链表的非尾节点(不能遍历链表) 

不能遍历链表说明找不到要删节点的前一个节点,不能常规删除,所以可以找到要删除节点的下一个节点ret,然后互换pos和ret的值,删除pos即可。

void DelListNode(Slist** pos)		//删除一个无头单链表的非尾节点
{
	if (*pos == NULL)
	{
		return;
	}
	if ((*pos)->next == NULL)
	{
		free(pos);
		pos = NULL;
	}
	else
	{
		Slist* ret = (*pos)->next;
		(*pos)->data = ret->data;
		(*pos)->next = ret->next;
		free(ret);
		ret = NULL;
	}

}

3.在无头单链表的一个节点前插入一个节点(不能遍历链表)

可以把要插入的节点插在pos的后边,然后交换这两个的值即可。

void PlistInsert(Slist **pos, DataType x)		//在无头单链表的一个节点前插入一个节点(不能遍历链表)
{
	if (*pos == NULL)
	{
		return;
	}
	else
	{
		Slist* cur = BuySlist(x);
		cur->next = (*pos)->next;
		(*pos)->next = cur;
		swap(&(*pos)->data, &cur->data);	
	}
}

4.单链表实现约瑟夫环(JosephCircle)

int SListJosephCircle(Slist* head, int k)
{
	if (head == NULL)
	{
		return -1;
	}
	if (head->next == NULL)
	{
		return head->data;
	}

	Slist* phead = head;
	while (phead->next!=NULL)		//成环
	{
		phead = phead->next;
	}
	phead->next = head;


	//实现过程
	Slist* p1 = head;
	Slist* p2 = head;
	Slist* cur = p1;
	while (cur->next!=NULL)
	{
		int ret = k - 1;
		while (ret--)
		{
			p1 = p2;
			p2 = p2->next;
		}
		if (p1->next->next == p1)		//剩下两个节点
		{
			free(p2);
			p2 = NULL;
			return p1->data;
		}

		Slist* tmp = p2;
		p2 = p2->next;
		free(tmp);
		tmp = NULL;
		p1->next = p2;
		cur = p1;
	}

	return cur->data;
	
}

5.逆置/反转单链表

void reverse_list(Slist **pphead)		//逆置/反转单链表
{
	if (*pphead == NULL||(*pphead)->next==NULL)
	{
		return ;
	}
	Slist* p1 = *pphead;
	Slist* p2 = p1->next;
	Slist* p3 = p2->next;
	p1->next = NULL;
	while (p3!=NULL)
	{
		p2->next = p1; 
		p1 = p2;
		p2 = p3;
		p3 = p2->next;
	}
	p2->next = p1;
	*pphead = p2;
}

6.单链表排序(冒泡排序&快速排序)

冒泡:


void bubble_sort(Slist **pphead)  //冒泡排序
{
	if (*pphead == NULL)
	{
		return;
	}
	int flag = 0;
	Slist* tail = NULL;
	while (tail != (*pphead)->next)
	{
		Slist* cur = *pphead;
		while (cur->next != tail)
		{
			if (cur->data > (cur->next)->data)
			{
				flag = 1;
				swap(&cur->data, &(cur->next)->data);
			}
			cur = cur->next;
		}

		tail = cur;
		if (flag == 0)		//已经有序
		{
			return;
		}
	}
}

选择:

void SeletSort(Slist** phead)		//选择排序
{
	if (*phead == NULL)
	{
		return;
	}
	Slist* p1 = *phead;
	while (p1->next != NULL)
	{
		Slist* min = p1;
		Slist* p2 = p1;
		while (p2!=NULL)
		{
			if (p2->data <= min->data)
			{
				min = p2;
			}
			p2 = p2->next;
		}
		if (min != p1)
		{
			swap(&min->data, &p1->data);
		}
		p1 = p1->next;
	}

}

7.合并两个有序链表,合并后依然有序

Slist* SListMerge(Slist* list1, Slist* list2)		//合并两量表为有序
{
	assert(list1&&list2);
	Slist* p1 = list1;
	Slist* p2 = list2;
	Slist* list3 = NULL;
	while (1)
	{
		if (p1->data <= p2->data)
		{
			ListPushback(&list3, p1->data);
			p1 = p1->next;
		}
		if (p1 == NULL)
		{
			break;
		}
		if (p1->data > p2->data)
		{
			ListPushback(&list3, p2->data);
			p2 = p2->next;
		}
		if (p2 == NULL)
		{
			break;
		}
	}
	Slist* p3 = list3;
	while(p3->next != NULL)
	{
		p3 = p3->next;
	}

	if (p1 == NULL)
	{
		p3->next = p2;

	}
	if (p2 == NULL)
	{
		p3->next = p1;;
	}
	return list3;
}

8.查找单链表的中间节点,要求只能遍历一次链表

void SListFindMidNode(Slist* list)		//查找中间节点  已经过测试无bug
{
	if (list == NULL)	//没有节点
	{
		return;
	}
	if (list->next == NULL)		//一个节点
	{
		printf("%d\n", list->data);
		return;
	}
	Slist* p1 = list;
	Slist* p2 = list;
	while ( p2 != NULL && p2->next != NULL)
	{		
		p2 = p2->next->next;
		if (p2 == NULL)
		{
			break;
		}
		p1 = p1->next;
	}
	
	if (p2 == NULL)		//偶数个节点
	{
		printf("%d  %d\n", p1->data, p1->next->data);
		return;
	}
	
	if (p2->next == NULL)		//奇数个节点
	{
		printf("%d \n", p1->data );
		return;
	}
}

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

void SListFindTailKNode(Slist* list, size_t k)		//倒数第K个节点
{
	if (list == NULL)
	{
		return;
	}
	Slist* p1 = list;
	Slist* p2 = list;
	while (k--)
	{
		p2 = p2->next;
	}

	while (p2 != NULL)
	{
		p2 = p2->next;
		p1 = p1->next;
	}
	printf("%d\n", p1->data);
}

10.删除链表的倒数第K个结点 

void SListFindTailKNode(Slist* list, size_t k)		//倒数第K个节点
{
	if (list == NULL)
	{
		return;
	}
	Slist* p1 = list;
	Slist* p2 = list;
	while (k--)
	{
		p2 = p2->next;
	}

	while (p2 != NULL)
	{
		p2 = p2->next;
		p1 = p1->next;
	}
	printf("%d\n", p1->data);
}


void SListDeletTailKNode(Slist* list, size_t k)		//删除倒数第K个节点
{
	if (list == NULL)
	{
		return;
	}
	Slist* p1 = list;
	Slist* pre = p1;
	Slist* p2 = list;
	while (k--)
	{
		p2 = p2->next;
	}

	while (p2 != NULL)
	{
		p2 = p2->next;
		pre = p1;
		p1 = p1->next;
	}
	DelListNode(&p1);
}

猜你喜欢

转载自blog.csdn.net/yc1515707718/article/details/80406969