您的位置:首页 > 其它

实现单链表及其基本操作

2017-03-26 03:42 477 查看
单链表的定义:

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针

(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

单链表分为: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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: