实现单链表及其基本操作

来源:互联网 发布:马东眼袋在哪割的 知乎 编辑:程序博客网 时间:2024/05/29 02:12

单链表的定义:

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

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

单链表分为: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的结点,找到了返回该结点的地址,否则返回NULLNode* 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不等于pospPreNode = 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;}elsepDelNode = 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的结点,找到了返回该结点的地址,否则返回NULLNode* Find(PNode pHead, DataType data){assert(NULL != pHead);while (pHead)if (pHead->_data == data)break;elsepHead = 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");}



0 0
原创粉丝点击