实现单链表及其基本操作
2017-03-26 03:42
477 查看
单链表的定义:
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针
(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
单链表分为:1,有头单链表 2,无头单链表
本次主要针对无头单链表
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/30/d41b29285b2427d305431caa5dacf8e0)
链表的声明
链表的基本操作
注意:
在传入参数时,当需要修改pHead的指向时,需要传入二级指针PNode *pHead
当不需要改变pHead的指向时,只需传入一级指针PNode pHead即可。
链表基本功能实现
///////////////只要改变了单链表的内容(指针指向内容),应使用PNode*二级指针。////////////////
///////////////不然的话,在函数中改变了pHead的内容,函数外pHead还是指向原来的地址//////////
// 构建一个新节点
Node* BuyNode(DataType data)
{
PNode pTemp = (PNode)malloc(sizeof(Node));
if (NULL != pTemp)
{
pTemp->_data = data;
pTemp->_pNext = NULL;
}
return pTemp;
}
// 初始化单链表
void InitList(PNode* pHead)
{
assert(NULL != pHead);
*pHead = NULL; //初始化为空
}
// 在单链表的尾部插入一个节点
void PushBack(PNode* pHead, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pHead);
if (!(pNewNode = BuyNode(data))) //创建节点失败
return ;
if (NULL == *pHead) //链表为空时
*pHead = pNewNode;
else //链表不为空
{
PNode pTailNode = Back(*pHead);
pTailNode->_pNext = pNewNode;
}
}
// 在单链表的头部插入值为data的结点
void PushFront(PNode* pHead, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pHead);
if (!(pNewNode = BuyNode(data)))//创建节点失败
return ;
if (NULL == *pHead) //链表为空时
*pHead = pNewNode;
else //链表不为空
{
pNewNode->_pNext = *pHead;
*pHead = pNewNode;
}
}
// 删除单链表的最后一个节点
void PopBack(PNode* pHead)
{
assert(NULL != pHead);
if (NULL == *pHead) //链表为空
return ;
if (NULL == (*pHead)->_pNext) //链表只有一个节点
{
free(*pHead); //删除节点
*pHead = NULL; //链表为空
}
else //链表节点大于等于2
{
PNode pDelNode = *pHead; //倒数第二个节点指针
while (NULL != pDelNode->_pNext->_pNext) //指向倒数第二个节点
pDelNode = pDelNode->_pNext;
free(pDelNode->_pNext); //删除最后一个节点
pDelNode->_pNext = NULL; //倒数第二个节点指向空。
}
}
// 删除单链表的第一个结点
void PopFront(PNode* pHead)
{
assert(NULL != pHead);
if (NULL == *pHead)
return ;
else
{
PNode pFirstNode = *pHead;
*pHead = (*pHead)->_pNext;
free(pFirstNode);
pFirstNode = NULL;
}
}
// 在单链表pos位置后插入值为data的结点
void Insert(PNode pos, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pos);
if (!(pNewNode = BuyNode(data)))
return ;
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
}
// 在单链表中删除位置为pos的结点
void Erase(PNode* pHead, PNode pos)
{
PNode pPreNode = NULL;
assert(NULL != pHead); //看看是该用if(pos == NULL)好,还是assert好。
assert(NULL != pos);
pPreNode = *pHead; //pPreNode指向pos前一节点
if (NULL == *pHead) //当是空链表时
return ;
if (pos == *pHead) //pos为第一个节点时
PopFront(pHead);
else //pos为别的位置,并且链表不为空
{ //考虑pos不为链表内容情况
while (pPreNode && pPreNode->_pNext != pos) //pCurNode指向不为空且pCurNode->_pNext不等于pos
pPreNode = pPreNode->_pNext; //pCurNode指向下一节点
if (NULL != pPreNode) //pCurNode下一节点是pos
{
pPreNode->_pNext = pos->_pNext;
free(pos);
pos = NULL;
}
}
}
// 移除单链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data)
{
PNode pDelNode = NULL;
assert(NULL != pHead);
if (pDelNode = Find(*pHead, data))
Erase(pHead, pDelNode);
}
// 移除单链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data)
{
PNode pDelNode = NULL;
assert(NULL != pHead);
pDelNode = *pHead;
if (NULL == *pHead) //链表为空
return ;
if (NULL == (*pHead)->_pNext) //链表只有一个节点
{
if ((*pHead)->_data == data)
PopFront(pHead);
}
else
{ //思路:将本该删除的节点pDelNode替换为它的下一节点pTemp,然后释放pTemp。
while (pDelNode->_pNext)
if (pDelNode->_data == data)
{
PNode pTemp = pDelNode->_pNext;
pDelNode->_data = pTemp->_data;
pDelNode->_pNext = pTemp->_pNext;
free(pTemp);
pTemp = NULL;
}
else
pDelNode = pDelNode->_pNext;
}
}
//销毁链表
void DestroyList(PNode *pHead)
{
PNode pCurNode = NULL;
assert(NULL == pHead);
while (NULL != *pHead)
{
PNode pTemp = *pHead;
*pHead = (*pHead)->_pNext;
free(pTemp);
pTemp = NULL;
}
}
///////////////////////////////////////
// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(PNode pHead, DataType data)
{
assert(NULL != pHead);
while (pHead)
if (pHead->_data == data)
break;
else
pHead = pHead->_pNext;
return pHead;
}
// 获取单链表总结点的总个数
size_t Size(PNode pHead)
{
size_t n = 0;
while (pHead) //当pHead不为空时
{
++n;
pHead = pHead->_pNext;
}
return n;
}
// 判断结点是否为空
int Empty(PNode pHead)
{
if (pHead) //pHead不是空链表
return 1;
return 0;
}
// 返回单链表的最后一个结点的位置
PNode Back(PNode pHead)
{
if (NULL != pHead) //pHead不是空链表
while (pHead->_pNext)
pHead = pHead->_pNext;
return pHead;
}
// 返回单链表的第一个结点的位置
PNode Front(PNode pHead)
{
return pHead;
}
// 正向打印单链表
void PrintList(PNode pHead)
{
PNode pCurNode = NULL;
assert(NULL != pHead);
pCurNode = pHead;
while (pCurNode)
{
printf("%d->", pCurNode->_data);
pCurNode = pCurNode->_pNext;
}
printf("<null>\n");
}
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针
(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
单链表分为:1,有头单链表 2,无头单链表
本次主要针对无头单链表
链表的声明
#include <stdio.h> #include <assert.h> #include <malloc.h> typedef int DataType; //带头单链表 typedef struct Node { DataType _data; struct Node* _pNext; }Node, *PNode;
链表的基本操作
注意:
在传入参数时,当需要修改pHead的指向时,需要传入二级指针PNode *pHead
当不需要改变pHead的指向时,只需传入一级指针PNode pHead即可。
// 初始化单链表 void InitList(PNode* pHead); //销毁链表 void DestroyList(PNode *pHead); // 在单链表的尾部插入一个节点 void PushBack(PNode* pHead, DataType data); // 删除单链表的最后一个节点 void PopBack(PNode* pHead); // 在单链表的头部插入值为data的结点 void PushFront(PNode* pHead, DataType data); // 删除单链表的第一个结点 void PopFront(PNode* pHead); // 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL Node* Find(PNode pHead, DataType data); // 在单链表pos位置后插入值为data的结点 void Insert(PNode pos, DataType data); // 在单链表中删除位置为pos的结点 void Erase(PNode* pHead, PNode pos); // 移除单链表中第一个值为data的结点 void Remove(PNode* pHead, DataType data); // 移除单链表中所有值为data的结点 void RemoveAll(PNode* pHead, DataType data); // 获取单链表总结点的总个数 size_t Size(PNode pHead); // 判断结点是否为空 int Empty(PNode pHead); // 返回单链表的最后一个结点的位置 PNode Back(PNode pHead); // 返回单链表的第一个结点的位置 PNode Front(PNode pHead); // 构建一个新节点 Node* BuyNode(DataType data); // 正向打印单链表 void PrintList(PNode pHead);
链表基本功能实现
///////////////只要改变了单链表的内容(指针指向内容),应使用PNode*二级指针。////////////////
///////////////不然的话,在函数中改变了pHead的内容,函数外pHead还是指向原来的地址//////////
// 构建一个新节点
Node* BuyNode(DataType data)
{
PNode pTemp = (PNode)malloc(sizeof(Node));
if (NULL != pTemp)
{
pTemp->_data = data;
pTemp->_pNext = NULL;
}
return pTemp;
}
// 初始化单链表
void InitList(PNode* pHead)
{
assert(NULL != pHead);
*pHead = NULL; //初始化为空
}
// 在单链表的尾部插入一个节点
void PushBack(PNode* pHead, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pHead);
if (!(pNewNode = BuyNode(data))) //创建节点失败
return ;
if (NULL == *pHead) //链表为空时
*pHead = pNewNode;
else //链表不为空
{
PNode pTailNode = Back(*pHead);
pTailNode->_pNext = pNewNode;
}
}
// 在单链表的头部插入值为data的结点
void PushFront(PNode* pHead, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pHead);
if (!(pNewNode = BuyNode(data)))//创建节点失败
return ;
if (NULL == *pHead) //链表为空时
*pHead = pNewNode;
else //链表不为空
{
pNewNode->_pNext = *pHead;
*pHead = pNewNode;
}
}
// 删除单链表的最后一个节点
void PopBack(PNode* pHead)
{
assert(NULL != pHead);
if (NULL == *pHead) //链表为空
return ;
if (NULL == (*pHead)->_pNext) //链表只有一个节点
{
free(*pHead); //删除节点
*pHead = NULL; //链表为空
}
else //链表节点大于等于2
{
PNode pDelNode = *pHead; //倒数第二个节点指针
while (NULL != pDelNode->_pNext->_pNext) //指向倒数第二个节点
pDelNode = pDelNode->_pNext;
free(pDelNode->_pNext); //删除最后一个节点
pDelNode->_pNext = NULL; //倒数第二个节点指向空。
}
}
// 删除单链表的第一个结点
void PopFront(PNode* pHead)
{
assert(NULL != pHead);
if (NULL == *pHead)
return ;
else
{
PNode pFirstNode = *pHead;
*pHead = (*pHead)->_pNext;
free(pFirstNode);
pFirstNode = NULL;
}
}
// 在单链表pos位置后插入值为data的结点
void Insert(PNode pos, DataType data)
{
PNode pNewNode = NULL;
assert(NULL != pos);
if (!(pNewNode = BuyNode(data)))
return ;
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
}
// 在单链表中删除位置为pos的结点
void Erase(PNode* pHead, PNode pos)
{
PNode pPreNode = NULL;
assert(NULL != pHead); //看看是该用if(pos == NULL)好,还是assert好。
assert(NULL != pos);
pPreNode = *pHead; //pPreNode指向pos前一节点
if (NULL == *pHead) //当是空链表时
return ;
if (pos == *pHead) //pos为第一个节点时
PopFront(pHead);
else //pos为别的位置,并且链表不为空
{ //考虑pos不为链表内容情况
while (pPreNode && pPreNode->_pNext != pos) //pCurNode指向不为空且pCurNode->_pNext不等于pos
pPreNode = pPreNode->_pNext; //pCurNode指向下一节点
if (NULL != pPreNode) //pCurNode下一节点是pos
{
pPreNode->_pNext = pos->_pNext;
free(pos);
pos = NULL;
}
}
}
// 移除单链表中第一个值为data的结点
void Remove(PNode* pHead, DataType data)
{
PNode pDelNode = NULL;
assert(NULL != pHead);
if (pDelNode = Find(*pHead, data))
Erase(pHead, pDelNode);
}
// 移除单链表中所有值为data的结点
void RemoveAll(PNode* pHead, DataType data)
{
PNode pDelNode = NULL;
assert(NULL != pHead);
pDelNode = *pHead;
if (NULL == *pHead) //链表为空
return ;
if (NULL == (*pHead)->_pNext) //链表只有一个节点
{
if ((*pHead)->_data == data)
PopFront(pHead);
}
else
{ //思路:将本该删除的节点pDelNode替换为它的下一节点pTemp,然后释放pTemp。
while (pDelNode->_pNext)
if (pDelNode->_data == data)
{
PNode pTemp = pDelNode->_pNext;
pDelNode->_data = pTemp->_data;
pDelNode->_pNext = pTemp->_pNext;
free(pTemp);
pTemp = NULL;
}
else
pDelNode = pDelNode->_pNext;
}
}
//销毁链表
void DestroyList(PNode *pHead)
{
PNode pCurNode = NULL;
assert(NULL == pHead);
while (NULL != *pHead)
{
PNode pTemp = *pHead;
*pHead = (*pHead)->_pNext;
free(pTemp);
pTemp = NULL;
}
}
///////////////////////////////////////
// 在单链表中查找值为data的结点,找到了返回该结点的地址,否则返回NULL
Node* Find(PNode pHead, DataType data)
{
assert(NULL != pHead);
while (pHead)
if (pHead->_data == data)
break;
else
pHead = pHead->_pNext;
return pHead;
}
// 获取单链表总结点的总个数
size_t Size(PNode pHead)
{
size_t n = 0;
while (pHead) //当pHead不为空时
{
++n;
pHead = pHead->_pNext;
}
return n;
}
// 判断结点是否为空
int Empty(PNode pHead)
{
if (pHead) //pHead不是空链表
return 1;
return 0;
}
// 返回单链表的最后一个结点的位置
PNode Back(PNode pHead)
{
if (NULL != pHead) //pHead不是空链表
while (pHead->_pNext)
pHead = pHead->_pNext;
return pHead;
}
// 返回单链表的第一个结点的位置
PNode Front(PNode pHead)
{
return pHead;
}
// 正向打印单链表
void PrintList(PNode pHead)
{
PNode pCurNode = NULL;
assert(NULL != pHead);
pCurNode = pHead;
while (pCurNode)
{
printf("%d->", pCurNode->_data);
pCurNode = pCurNode->_pNext;
}
printf("<null>\n");
}
相关文章推荐
- c语言实现单链表数据结构及其基本操作
- 单链表及其基本操作的实现
- 单链表的存储结构及其基本操作的实现
- 单链表及其基本操作(C语言实现)
- C语言实现单链表的基本操作及其部分面试题
- 双链表的实现及其基本操作
- 链表,顺序表的基本操作及其实现的栈与队列
- 带头节点的单链表及其基本操作(Java实现)
- c语言实现链表及其基本操作
- C语言实现单链表的基本操作及其部分面试题
- 链表及其基本操作的JAVA实现。
- 不带头节点的单链表及其基本操作(Java实现)
- 单链表的实现及其基本操作
- 详细的单链表基本操作C/C++实现
- 使用C++实现链表的基本操作
- 链表基本操作的程序实现(转)
- C语言实现单链表(带头结点)的基本操作(创建,头插法,尾插法,删除结点,打印链表)
- 链表基本操作的实现
- 链表的基本操作实现
- 块状链表基本操作及其相关例题