常见链表面试题集合

链表是面试或者笔试的重点内容,整理一片链表常见题型

链表面试题.h

列出解决面试题时经常使用的方法,例如打印、插入、删除等

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

//链表结构体定义
typedef int DataType;
typedef struct ListNode
{
	DataType data;
	struct ListNode *next;
}ListNode;

//链表初始化
void ListInit(ListNode **pFirst)
{
	assert(pFirst != NULL);
	*pFirst = NULL;
}

//链表销毁
void ListDestroy(ListNode **pFirst)
{
	ListNode *next = NULL;
	ListNode *cur;
	assert(pFirst != NULL);
	for(cur=*pFirst; cur != NULL; cur=next)
	{
		next = cur->next;
		free(cur);
	}
	*pFirst = NULL;
}

//创建新结点
ListNode *CreateNode(DataType data)
{
	ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

//链表的打印
int ListNodePrint(ListNode **pFirst)
{
	ListNode *cur = NULL;
	assert(pFirst);
	for(cur=*pFirst; cur != NULL; cur=cur->next)
	{
		printf("%d ",cur->data);
	}
	return 0;
}

//链表的插入
//头插
void ListPushFront(ListNode **pFirst, DataType data)
{
	ListNode *newNode;
	assert(pFirst != NULL); //指针不为空
	newNode = CreateNode(data);
	if(*pFirst == NULL)
	{
		*pFirst = newNode;
		newNode->next = NULL;
		return;
	}
	newNode->next = *pFirst;
	*pFirst = newNode;
}

//尾插
void ListPushBack(ListNode **pFirst, DataType data)
{
	ListNode *cur = NULL;
	ListNode *newNode = CreateNode(data);
	assert(pFirst != NULL);
	cur = *pFirst;
	if(*pFirst == NULL)
	{
		*pFirst = newNode;
		return;
	}
	while(cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = newNode;
}

//链表删除
//头删
void ListDeleteFront(ListNode **pFirst)
{
	ListNode *del = NULL;
	assert(pFirst != NULL);
	assert(*pFirst != NULL);
	del = *pFirst;
	*pFirst = del->next;
    free(del);
}

//尾删
void ListDeleteBack(ListNode **pFirst)
{
	ListNode *cur = NULL;
	ListNode *del = NULL;
	assert(pFirst != NULL); //指针不为空
	assert(*pFirst != NULL); //链表不为空

	if((*pFirst)->next == NULL) //链表中只有一个结点
	{
		free(*pFirst);
		*pFirst = NULL;
		return;
	}
	cur = *pFirst;
	while(cur->next->next != NULL)
	{
		cur = cur->next;
	}
	del = cur->next;
	cur->next = NULL;
	free(del);
}

//查找
ListNode *ListFind(ListNode *first, DataType data)
{
	ListNode *cur = NULL;
	for(cur=first; cur->next!=NULL; cur=cur->next)
	{
		if(cur->data == data)
		{
			return cur;
		}
	}
	return NULL;
}

//给定位置插入  pos
void ListInsert(ListNode **pFirst,ListNode *pos, DataType data)
{
	ListNode *cur = NULL;
	ListNode *newNode;
	//首先需找到POS前一个结点位置
	//特殊情况 pos指向首结点 头插
	if(pos == *pFirst)
	{
		ListPushFront(pFirst, data);
		return;
	}
	cur = *pFirst;
	while(cur->next != pos)
	{
		cur = cur->next;
	}
	newNode = CreateNode(data);
	newNode->next = cur->next;
	cur->next = newNode;
}

//给定位置的删除
void ListDelete(ListNode **pFirst, ListNode *pos)
{
	ListNode *cur = NULL;
	ListNode *del = NULL;
	if(pos == *pFirst)
	{
		ListDeleteFront(pFirst);
		return;
	}
	cur = *pFirst;
	while(cur->next != pos)
	{
		cur = cur->next;
	}
	del = cur->next;
	cur->next = cur->next->next;
	free(del);
}

test.c

链表题目以及测试函数:
逆序打印链表

//从尾到头打印链表
void PrintReverse(ListNode *pFirst)
{
	ListNode *cur = NULL;
	ListNode *end = NULL;
	while(end != pFirst)
	{
		cur = pFirst;
		while(cur->next != end)
		{
			cur = cur->next;
		}
		printf("%d ",cur->data);
		end = cur;
	}
}

链表逆置

//逆置链表
ListNode *ListReverse(ListNode *first)
{
	ListNode *cur = NULL;
	ListNode *result = NULL;
	ListNode *node = NULL;
	cur = first;
	while(cur != NULL)
	{
		node = cur;
		cur = cur->next;

		node->next = result;
		result = node;
	}
	return result;
}

无头链表的插入删除问题

//插入
void NofirstInsert(ListNode *pos, DataType data)
{
	ListNode *newnode = NULL;
	newnode = CreateNode(data);
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除
void NofirstDelete(ListNode *pos)
{
	ListNode *del = NULL;
	pos->data = pos->next->data;
	del = pos->next;
	pos->next = pos->next->next;
	free(del);
}

单链表实现约瑟夫环问题

//单链表实现约瑟夫环
ListNode *JosePhCycle(ListNode *first, int k)
{
	//链表构成环
	ListNode *tail = NULL;
	ListNode *cur = NULL;
	ListNode *del = NULL;
	int i = 0;
	tail = first;
	while(tail->next != NULL)
	{
		tail = tail->next;
	}
    //tail是最后一个结点,将它指向第一个结点
	tail->next = first;
	//从第一个结点开始,向后遍历进行删除
	cur = first;
	while(cur->next != cur)
	{
		for(i=0; i<k-1; i++)
		{
			del = cur;
			cur = cur->next;
		}
		del->next = cur->next;
		free(cur);
		cur = del->next;
	}
	cur->next = NULL;
	return cur;
}

求链表的中间结点

//查找单链表的中间结点
void FindMid(ListNode *first)
{
	ListNode *fast = NULL;
	ListNode *slow = NULL;
	fast = first;
	slow = first;
	//while(1)
	//{
	//	fast = fast->next;
	//	if(fast == NULL)
	//	{
	//		break;
	//	}
	//	fast = fast->next;
	//	slow = slow->next;
	//}
	while(fast->next != NULL && fast != NULL)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	printf("%d\n",slow->data);
}

取得链表倒数第K个结点

//查找链表的倒数第K个结点
void ListFindK(ListNode *first,int k)
{
	ListNode *forword = NULL;
	ListNode *backword = NULL;
    forword = first;
	backword = first;
	while(k--)
	{
		forword = forword->next;
	}
	while(forword != NULL)
	{
		forword = forword->next;
		backword = backword->next;
	}
	printf("%d\n",backword->data);
}

测试函数

void Test()
{
	ListNode *first;
	ListNode *List = NULL;
    ListInit(&first);

	ListPushFront(&first,5);
	ListPushFront(&first,4);
	ListPushFront(&first,3);
	ListPushFront(&first,2);
	ListPushFront(&first,1);

	//PrintReverse(first);
	//List = ListReverse(first);

	//NofirstDelete(first);
	//NofirstInsert(first,3);

	//List = JosePhCycle(first,3);
	FindMid(first);
	ListFindK(first,2);
	//ListNodePrint(&List);
    //printf("\n");
}

int main()
{
	Test();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ly52014/article/details/89578099