简单实现链表的基本操作:初始化,销毁,增删改查等操作。
SlistNode.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#pragma warning(disable:4996)
typedef int DataType;
typedef struct SlistNode
{
struct SlistNode *pNext;//指向链表中下一个结点
DataType data;//当前结点中所保存的元素
}SlistNode;
void Print(SlistNode *pFirst);//打印
void SlistInit(SlistNode **ppFirst);//初始化
void SlistDestroy(SlistNode **ppFirst);//销毁
void PushBack(SlistNode **ppFirst, DataType data);//尾插
void PushFront(SlistNode **ppFirst, DataType data);//头插
void Insert(SlistNode **ppFirst,SlistNode *pos, DataType data);//指定位置插入
void PopFront(SlistNode **ppFirst);//头删
void PopBack(SlistNode **ppFirst);//尾删
void Erase(SlistNode **ppFirst, SlistNode *pos);//任意结点删
SlistNode *Find(SlistNode *pFirst, DataType data);//查找,找到返回遇到的第一个结点的地址,没找到,返回NULL
void Remove(SlistNode **pFirst, DataType data);//根据数据删除,删除遇到的第一个结点
void RemoveAll(SlistNode **pFirst, DataType data);//根据数据删除,删除遇到的所有结点
SlistNode.c
#include"SlistNode.h"
void Print(SlistNode *pFirst)//打印
{
SlistNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext)
{
printf("%d-> ", pNode->data);
}
printf("NULL\n");
}
void SlistInit(SlistNode **ppFirst)//初始化
{
assert(ppFirst);
*ppFirst = NULL;
}
SlistNode * CreateNewNode(int data)//创造新节点
{
SlistNode *pNewNode = (SlistNode *)malloc(sizeof(SlistNode));
assert(pNewNode);
pNewNode->data = data;
pNewNode->pNext = NULL;
return pNewNode;
}
void PushBack(SlistNode **ppFirst, DataType data)//尾插
{
assert(ppFirst);
SlistNode *pNewNode=CreateNewNode(data);
if (*ppFirst == NULL)
{
*ppFirst = pNewNode;
return;
}
SlistNode *pNode;
pNode = *ppFirst;
while (pNode->pNext != NULL)
{
pNode = pNode->pNext;
}
pNode->pNext = pNewNode;
}
void PushFront(SlistNode **ppFirst, DataType data)//头插
{
assert(ppFirst);
SlistNode *pNewNode=CreateNewNode(data);
pNewNode->pNext = *ppFirst;
*ppFirst = pNewNode;
}
void Insert(SlistNode **ppFirst, SlistNode *pos, DataType data)//指定位置插入
{
assert(ppFirst);
SlistNode *pNode;
pNode = *ppFirst;
if (pos == *ppFirst)//判断第一个结点是否为要找的结点
{
PushFront(ppFirst, data);//是,就为头插
return;
}
while (pNode->pNext != pos)
{
pNode = pNode->pNext;
}
SlistNode *pNewNode = CreateNewNode(data);
pNode->pNext = pNewNode;
pNewNode->pNext = pos;
}
SlistNode *Find(SlistNode *pFirst, DataType data)//查找,找到返回遇到的第一个结点的地址,没找到,返回NULL
{
SlistNode *pNode;
for (pNode = pFirst; pNode; pNode = pNode->pNext)
{
if (pNode->data = data)
{
return pNode;
}
}
return NULL;
}
void PopFront(SlistNode **ppFirst)//头删
{
assert(ppFirst);
SlistNode *pOldNode = *ppFirst;
*ppFirst = (*ppFirst)->pNext;
free(pOldNode);
}
void PopBack(SlistNode **ppFirst)//尾删
{
assert(ppFirst);
assert(*ppFirst);
if ((*ppFirst)->pNext == NULL)
{
free(*ppFirst);
*ppFirst = NULL;
return;
}
SlistNode *pNode = *ppFirst;
while (pNode->pNext->pNext != NULL)
{
pNode = pNode->pNext;
}
free(pNode->pNext);
pNode = pNode->pNext;
}
void Erase(SlistNode **ppFirst, SlistNode *pos)//任意结点删
{
assert(ppFirst);
assert(*ppFirst);
if ((*ppFirst == pos))
{
PopFront(ppFirst);//头删
return;
}
SlistNode *pCur = *ppFirst;
while (pCur->pNext != pos)
{
pCur = pCur->pNext;
}
pCur->pNext = pos->pNext;
free(pos);
}
void SlistDestroy(SlistNode **ppFirst)//销毁
{
assert(ppFirst);
SlistNode *pNode;
SlistNode *pNext;
pNode = *ppFirst;
while (pNode != NULL)
{
pNext = pNode->pNext;
free(pNode);
pNode = pNext;
}
*ppFirst = NULL;
}
void Remove(SlistNode **ppFirst, DataType data)//根据数据删除,删除遇到的第一个结点
{
SlistNode *pFound = Find(*ppFirst, data);
if (pFound != NULL)
{
Erase(ppFirst, pFound);
}
}
//void RemoveAll(SlistNode **ppFirst, DataType data)//根据数据删除,删除遇到的所有结点
{
SlistNode *pNode = *ppFirst;
SlistNode *pNext;
while (pNode->pNext)
{
if (pNode->pNext->data == data)
{
pNext = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
free(pNext);
}
else
{
pNode = pNode->pNext;
}
}
if ((*ppFirst)->data == data)
{
PopFront(ppFirst);
}
}
有些链表常考的面试题,分别为:
- 倒叙打印链表
void ReversePrint(SlistNode *pFirst)
{
SlistNode *pNode = pFirst;
if (pNode->pNext)
{
ReversePrint(pNode->pNext);
}
printf("%d->", pNode->data);
}
- 逆置链表
SlistNode * ReverseList(SlistNode *pFirst)
{
/*SlistNode *p1 = NULL;
SlistNode *p2 = pFirst;
SlistNode *p3 = pFirst->pNext;
while (p2)
{
p2->pNext = p1;
p1= p2;
p2 = p3;
if (p3 != NULL)
{
p3 = p3->pNext;
}
}
return p1;
*/
SlistNode *pNewFirst = NULL;
DataType data;
while (pFirst != NULL)
{
data = pFirst->data;
PopFront(&pFirst);//头删
PushFront(&pNewFirst, data);//头插
}
return pNewFirst;
}
- 删除非尾无头链表
void RemoveNodeNotTail(SlistNode *pos)
{
assert(pos);
SlistNode *pNode = pos->pNext;
pos->pNext = pNode->pNext;
pos->data = pNode->data;
free(pNode);
}
- 无头链表前插入
void InsertNoHead(SlistNode *pos, int data)
{
SlistNode *pNode = (SlistNode *)malloc(sizeof(SlistNode));
assert(pNode);
pNode->data = pos->data;
pNode->pNext = pos->pNext;
pos -> pNext=pNode;
pos->data = data;
}
- 约瑟夫环
SlistNode * JocephCircle(SlistNode *pFirst, int k)
{
SlistNode *pNode = pFirst;
SlistNode *pRev = NULL;
int i = 0;
//用单链表构建出环
while (pNode->pNext)
{
pNode = pNode->pNext;
}
pNode ->pNext= pFirst;
//开始循环
pNode = pFirst;
while (pNode->pNext != pNode)
{
for ( i = 0; i < k - 1; i++)
{
pRev = pNode;
pNode = pNode->pNext;
}
pRev->pNext = pNode->pNext;
free(pNode);
pNode = pRev->pNext;
}
return pNode;
}
- 冒泡排序
void BubbleSort(SlistNode *pFirst)
{
SlistNode * pCur = NULL;
SlistNode *tail = NULL;
assert(pFirst);
pCur = pFirst;
if ((pFirst== NULL) || (pFirst->pNext == NULL))
{
return;
}
while (pCur != tail) //当尾指针不等于头指针时进行冒泡
{
while (pCur->pNext != tail) //控制pCur指针最后到的位置是倒数第二个节点
{
if (pCur->data >pCur->pNext->data)
{
int tmp = pCur->data;
pCur->data = pCur->pNext->data;
pCur->pNext->data = tmp;
}
pCur = pCur->pNext;
}
tail = pCur;
pCur = pFirst;
}
return;
}
- 合并两个有序链表
SlistNode * MergeOrderedList(SlistNode *p1First, SlistNode *p2First)
{
SlistNode *p1 = p1First;
SlistNode *p2 = p2First;
SlistNode *pNew = NULL;
//两个都不为空
while (p1 != NULL &&p2 != NULL)
{
if (p1->data < p2->data)
{
PushBack(&pNew, p1->data);
p1 = p1->pNext;
}
else
{
PushBack(&pNew, p2->data);
p2 = p2->pNext;
}
}
//有一个为空了
SlistNode *pNotempty = p1;//假设p1不为空
if (p1 == NULL)
{
pNotempty = p2;
}
while (pNotempty)
{
PushBack(&pNew, pNotempty->data);
pNotempty = pNotempty->pNext;
}
return pNew;
}
- 遍历一次,找到中间结点
SlistNode * FindMid(SlistNode *pFirst)
{
SlistNode *pFast = pFirst;
SlistNode *pSlow = pFirst;
while (1)
{
pFast = pFast->pNext;
if (pFast == NULL)
{
break;
}
pFast = pFast->pNext;
if (pFast == NULL)
{
break;
}
pSlow = pSlow->pNext;
}
return pSlow;
}
- 遍历一次,找到倒数第 k 个结点(k从1开始)
SlistNode * FindK(SlistNode *pFirst, int k)
{
SlistNode *pSlow = pFirst;
SlistNode *pFast = pFirst;
if (NULL == pFirst || k< 0)
return NULL;
//让pFast先走K步
while (k--)
{
if (NULL == pFast)//K大于节点个数
return NULL;
pFast = pFast->pNext;
}
//两指针同时往后走
while (pFast)
{
pFast = pFast->pNext;
pSlow = pSlow->pNext;
}
return pSlow;
}
- 遍历一次,删除倒数第 k 个结点(k从1开始),不能用替换删除法
void RemoveK(SlistNode *pFirst, int k)
{
SlistNode *pSlow = pFirst;
SlistNode *pFast = pFirst;
SlistNode *pPre = NULL;
if (NULL == pFirst || k< 0)
return NULL;
//让pFast先走K步
while (k--)
{
if (NULL == pFast)//K大于节点个数
return NULL;
pFast = pFast->pNext;
}
//两指针同时往后走
while (pFast)
{
pPre = pSlow;
pFast = pFast->pNext;
pSlow = pSlow->pNext;
}
//删除
pPre->pNext = pSlow->pNext;
free(pSlow);
}
11.复制复杂链表
typedef struct RandomListNode {
int label;
struct RandomListNode *next, *random;
}RandomListNode;
RandomListNode* Clone(RandomListNode* pHead)
{
RandomListNode* pNode;
RandomListNode* pOldRandom;
RandomListNode* pNewNode;
RandomListNode* pNewRandom;
//复制结点
for (pNode = pHead; pNode; pNode = pNode->next->next)
{
pNewNode = (RandomListNode *)malloc(sizeof(RandomListNode));
pNewNode->label = pNode->label;
pNewNode->next = pNode->next;
pNewNode->random = NULL;
pNode->next = pNewNode;
}
//复制结点random
for (pNode = pHead; pNode; pNode = pNode->next->next)
{
pNewNode = pNode->next;
pOldRandom = pNode->random;
if (pOldRandom != NULL)
{
pNewRandom = pOldRandom->next;
pNewNode->random = pNewRandom;
}
}
//拆链表
RandomListNode *pNewFirst = pHead->next;
for (pNode = pHead; pNode; pNode = pNode->next)
{
pNewNode = pNode->next;
pNode->next = pNewNode->next;
if (pNode->next != NULL)
{
pNewNode->next= pNode->next->next;
}
else
{
pNewNode->next = NULL;
}
}
return pNewFirst;
}