链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点
链表分为:
单链表
双链表
双向循环链表
链表与顺序表的比较:
顺序表支持随机访问,单链表不支持随机访问
顺序表插入/删除数据效率很低,时间复杂度为O(N)(除尾插尾删),单链表插入/删除效率更高,时间复杂度为O(1)
顺序表的高速缓存效率更高,单链表CPU高速缓存效率低
这里介绍单链表的基本操作:
结构:
typedef struct SListPNode
{
DataType _Data;
struct SListPNode* _pNext; //指向下一节点的指针
}Node, *PNode;
创建新节点:
PNode BuySListNode(DataType data)
{
PNode NewNode = (PNode)malloc(sizeof(Node));
if (NULL == NewNode)
{
return NULL;
}
NewNode->_Data = data;
NewNode->_pNext = NULL;
return NewNode;
}
初始化:
void SListInit(PNode *ppHead)
{
assert(ppHead);
*ppHead = NULL;
}
头插:
void SListPushFront(PNode *ppHead, DataType data)
{
assert(ppHead);
PNode NewNode = BuySListNode(data);
if (NULL == NewNode)
{
return;
}
NewNode->_pNext = *ppHead;
*ppHead = NewNode;
}
头删:
void SListPopFront(PNode *ppHead)
{
PNode pDel = NULL;
assert(ppHead);
if (NULL == *ppHead) //链表为空
{
return;
}
else
{
PNode pDel = *ppHead; //移动头结点
*ppHead = pDel->_pNext;
free(pDel); //删除
}
}
尾插:
void SListPushBack(PNode *ppHead, DataType data)
{
PNode pNewNode = NULL;
assert(ppHead);
pNewNode = BuySListNode(data);
if (NULL == pNewNode)
{
return;
}
if (NULL == *ppHead) //空链表
{
*ppHead = pNewNode;
}
else
{
PNode pTailNode = *ppHead;
while (pTailNode->_pNext) //从头结点开始找到最后一个节点的位置
{
pTailNode = pTailNode->_pNext;
}
pTailNode->_pNext = pNewNode;
}
}
尾删:
void SListPopBack(PNode *ppHead)
{
assert(ppHead);
if (NULL == *ppHead) //空链表
{
return;
}
else if (NULL ==(*ppHead)->_pNext) //只有一个节点
{
free(*ppHead);
*ppHead = NULL;
}
else
{
PNode pTail = *ppHead; //标记最后一个节点
PNode pPreTail = NULL; //标记最后一个节点的前一个节点
while (pTail->_pNext)
{
pPreTail = pTail;
pTail = pTail->_pNext;
}
free(pTail);
pPreTail->_pNext = NULL;
}
}
任意插入:
void SListInsert(PNode *ppHead, PNode pos, DataType data)
{
assert(ppHead);
PNode pPreNode = NULL;
if (NULL == pos || NULL == *ppHead) //pos不存在或是空表
{
return;
}
else
{
PNode pNewNode = BuySListNode(data);
if (*ppHead == pos) //头插
{
pNewNode->_pNext = *ppHead;
*ppHead = pNewNode;
}
else
{
pPreNode = *ppHead;
while (pPreNode && pPreNode->_pNext != pos) //找到pos前一个节点
{
pPreNode = pPreNode->_pNext;
}
if (pPreNode)
{
pNewNode->_pNext = pos;
pPreNode->_pNext = pNewNode;
}
else
{
return;
}
}
}
}
任意删除:
void SListErase(PNode *ppHead, PNode pos)
{
assert(ppHead);
if (NULL == *ppHead || NULL == pos)
{
return;
}
else
{
if (*ppHead == pos) //头删
{
*ppHead = pos->_pNext;
free(pos);
}
else
{
PNode pPrepos = *ppHead;
while (pPrepos && pPrepos->_pNext != pos)
{
pPrepos = pPrepos->_pNext;
}
if (pPrepos)
{
pPrepos->_pNext = pos->_pNext;
free(pos);
}
else
{
return;
}
}
}
}
查找:
PNode Find(PNode pHead, DataType data)
{
PNode pCur = pHead;
while (pCur)
{
if (data == pCur->_Data)
{
return pCur;
}
pCur = pCur->_pNext;
}
return NULL;
}
递归查找:
PNode FindBack_D(PNode pHead, DataType data)
{
if (pHead != NULL)
{
if (data == pHead->_Data)
return pHead;
return FindBack_D(pHead->_pNext, data); //此处return返回,不能直接递归调用
}
return NULL;
}
打印:
void SListPrint(PNode pHead)
{
PNode pCur = pHead;
while (pCur)
{
printf(" %d->", pCur->_Data);
pCur = pCur->_pNext;
}
printf("NULL\n");
}
销毁:
void SListDestroy(PNode* ppHead)
{
PNode pCur = NULL;
PNode pPreCur = NULL;
assert(ppHead);
pCur = *ppHead;
while (pCur)
{
pPreCur = pCur;
pCur = pCur->_pNext;
free(pPreCur);
}
*ppHead = NULL;
//while (pCur)
//{
// *ppHead = pCur->_pNext;
// free(pCur);
// pCur = *ppHead;
//}
}
SList.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct SListPNode
{
DataType _Data;
struct SListPNode* _pNext; //指向下一节点的指针
}Node, *PNode;
void SListInit(PNode *ppHead); //初始化
void SListPushBack(PNode *ppHead, DataType data); //尾插
void SListPopBack(PNode *ppHead); //尾删
void SListPushFront(PNode *ppHead, DataType data); //头插
void SListPopFront(PNode *ppHead); //头删
PNode BuySListNode(DataType data); //创建新节点
PNode Find(PNode pHead, DataType data); //查找
void SListInsert(PNode *ppHead,PNode pos, DataType data); //任意位置插入(插入pos前)
void SListErase(PNode *ppHead, PNode pos); //任意位置删除
unsigned long SListSize(PNode pHead); //链表结点个数
int SListEmpty(PNode pHead); //链表判空
void SListDestroy(PNode* ppHead); //链表销毁
void SListDestroy_D(PNode* ppHead); //链表递归销毁
void SListPrint(PNode pHead); //链表打印
SList.c#include "SList.h"
PNode BuySListNode(DataType data)
{
PNode NewNode = (PNode)malloc(sizeof(Node));
if (NULL == NewNode)
{
return NULL;
}
NewNode->_Data = data;
NewNode->_pNext = NULL;
return NewNode;
}
void SListInit(PNode *ppHead)
{
assert(ppHead);
*ppHead = NULL;
}
void SListPushBack(PNode *ppHead, DataType data)
{
PNode pNewNode = NULL;
assert(ppHead);
pNewNode = BuySListNode(data);
if (NULL == pNewNode)
{
return;
}
if (NULL == *ppHead)
{
*ppHead = pNewNode;
}
else
{
PNode pTailNode = *ppHead;
while (pTailNode->_pNext)
{
pTailNode = pTailNode->_pNext;
}
pTailNode->_pNext = pNewNode;
}
}
void SListPopBack(PNode *ppHead)
{
assert(ppHead);
if (NULL == *ppHead)
{
return;
}
else if (NULL ==(*ppHead)->_pNext)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
PNode pTail = *ppHead;
PNode pPreTail = NULL;
while (pTail->_pNext)
{
pPreTail = pTail;
pTail = pTail->_pNext;
}
free(pTail);
pPreTail->_pNext = NULL;
}
}
void SListPushFront(PNode *ppHead, DataType data)
{
assert(ppHead);
PNode NewNode = BuySListNode(data);
if (NULL == NewNode)
{
return;
}
NewNode->_pNext = *ppHead;
*ppHead = NewNode;
}
void SListPopFront(PNode *ppHead)
{
PNode pDel = NULL;
assert(ppHead);
if (NULL == *ppHead)
{
return;
}
else
{
PNode pDel = *ppHead;
*ppHead = pDel->_pNext;
free(pDel);
}
}
PNode Find(PNode pHead, DataType data)
{
PNode pCur = pHead;
while (pCur)
{
if (data == pCur->_Data)
{
return pCur;
}
pCur = pCur->_pNext;
}
return NULL;
}
void SListInsert(PNode *ppHead, PNode pos, DataType data)
{
assert(ppHead);
PNode pPreNode = NULL;
if (NULL == pos || NULL == *ppHead)
{
return;
}
else
{
PNode pNewNode = BuySListNode(data);
if (*ppHead == pos) //头插
{
pNewNode->_pNext = *ppHead;
*ppHead = pNewNode;
}
else
{
pPreNode = *ppHead;
while (pPreNode && pPreNode->_pNext != pos)//找到pos前一个节点
{
pPreNode = pPreNode->_pNext;
}
if (pPreNode)
{
pNewNode->_pNext = pos;
pPreNode->_pNext = pNewNode;
}
else
{
return;
}
}
}
}
void SListErase(PNode *ppHead, PNode pos)
{
assert(ppHead);
if (NULL == *ppHead || NULL == pos)
{
return;
}
else
{
if (*ppHead == pos)//头删
{
*ppHead = pos->_pNext;
free(pos);
}
else
{
PNode pPrepos = *ppHead;
while (pPrepos && pPrepos->_pNext != pos)
{
pPrepos = pPrepos->_pNext;
}
if (pPrepos)
{
pPrepos->_pNext = pos->_pNext;
free(pos);
}
else
{
return;
}
}
}
}
int SListEmpty(PNode pHead)
{
return NULL == pHead;
}
unsigned long SListSize(PNode pHead)
{
unsigned long count = 0;
PNode pCur = pHead;
while (pCur)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
//正向销毁
void SListDestroy(PNode* ppHead)
{
PNode pCur = NULL;
PNode pPreCur = NULL;
assert(ppHead);
pCur = *ppHead;
while (pCur)
{
pPreCur = pCur;
pCur = pCur->_pNext;
free(pPreCur);
}
*ppHead = NULL;
//while (pCur)
//{
// *ppHead = pCur->_pNext;
// free(pCur);
// pCur = *ppHead;
//}
}
//逆向销毁
void SListDestroy_D(PNode* ppHead)
{
assert(ppHead);
if (*ppHead)
{
SListDestroy_D(&(*ppHead)->_pNext);
free(*ppHead);
*ppHead = NULL;
}
}
void SListPrint(PNode pHead)
{
PNode pCur = pHead;
while (pCur)
{
printf(" %d->", pCur->_Data);
pCur = pCur->_pNext;
}
printf("NULL\n");
}