链表是面试或者笔试的重点内容,整理一片链表常见题型
链表面试题.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;
}