【Data_Structure笔记2】线性表的链式存储【单链表】
2017-08-25 16:26
483 查看
/************************************************************************************************************************ 文件说明: 线性表的链式存储之【单链表】、【双链表】、【循环链表】、【静态链表】 详细说明: 【1】由于顺序表的插入、删除操作需要大量的移动元素,而大量的移动元素这一操作会严重影响算法的性能,那么如何克服顺序表 操作中的这一缺点呢?这就引出了我们今天将要学习的线性表的链式存储之【单链表】。 【2】线性表的链式存储不需要使用地址连续的的存储单元,也不需要逻辑上相邻的元素之间,物理位置上也相邻,它是通过“链”, 即指针建立起数据元素之间的逻辑关系,因此,对线性表的插入、删除不需要移动元素,只需要修改相应的指针即可。 【3】链式存储:不要求逻辑上相邻的元素在物理位置上也相邻,借助指针来表示元素之间的逻辑关系,其优点是:不出出现内存的 碎片现象,充分利用了内存中的所有存储单元;缺点是:每个数据元素节点占用较多的存储空间,并且只能实现顺序存储,不 能实现【随机存取】。 【4】顺序存储:要求逻辑上相邻的数据元素之间,物理位置上也必须相邻,元素之间的逻辑关系由存储单元之间的邻接关系表示。 其优点是:每个元素占用较少的存储空间,并且可以实现随机存取;缺点是:只能使用相邻的一整块存储单元,因此,可能会 产生较多的碎片现象。 单链表: 【1】【单链表】:线性表的链式存储称为单链表,它是通过一组任意的存储单元来存储线性表中的数据元素的。 【2】为了建立起数据元素之间的线性关系,对每个链表的结点,除了存放元素自身的信息之外,还需要存放一个指向其后继的指针。 单链表的结点一般分为两个域,【数据域】和【指针域】。 *************************************************************************************************************************/ #include<iostream> #include<string> using namespace std; /************************************************************************************************************************* 单链表的11中算法: 【1】初始化单链表的操作 【2】头插法建立单链表 【3】尾插法建立单链表 【4】打印单链表,单链表的遍历 【5】清除线性表中的所有元素,即释放单链表pHead中所有的结点,使之成为一个空表 【6】返回单链表的实际长度 【7】检查单链表是否为空,若为空,则返回1,否则返回0 【8】按序号查找结点值 【9】按值查找表结点 【10】插入结点操作 【11】删除结点操作 **************************************************************************************************************************/ typedef int ElemType; /************************************************************************************************************************* 模块说明: 单链表中,结点类型的描述 **************************************************************************************************************************/ typedef struct LNode { ElemType data; //【1】数据域 struct LNode* next; //【2】指针域 }LNode,*LinkList; /************************************************************************************************************************* 函数原型: void InitList(LinkList& pHead) 函数说明: 【1】初始化单链表的操作 【2】pHead是指向单链表头结点的指针,用来接收主程序中待初始化单链表的头指针变量 **************************************************************************************************************************/ void InitList(LinkList& pHead) { pHead = (LinkList)std::malloc(sizeof(LNode)); //【1】创建头结点 pHead->next = NULL; //【2】建立空的单链表 std::cout<<"【NOTICE】InitList函数被执行,初始化一个空单链表成功!"<<std::endl; } /************************************************************************************************************************* 函数原型: LinkList CreatListHead(LinkList& pHead) 函数说明: 【1】通常用一个【头指针】来标识一个单链表,如单链表L,头指针为"NULL"时,则表示一个空表。此外,为了操作上的方便,在单 链表第一个结点之前附加一个结点,称为【头结点】。 【2】采用头插法建立单链表 该方法从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即 头结点之后。 【3】采用头插法建立单链表,读入数据的顺序与生成的链表中元素的顺序是相反的。 **************************************************************************************************************************/ LinkList CreatListHead(LinkList& pHead) { LNode* insertNode = NULL; int insertData = 0; std::cout<<"【NOTICE】请输入单链表第一个要插入结点的数据insertData:"; std::cout<<std::endl; std::cin>>insertData; //【1】输入新结点数据域的值 while(insertData!=9999) { insertNode = (LNode*)std::malloc(sizeof(LNode)); //【2】创建新结点 insertNode->data = insertData; insertNode->next = pHead->next; pHead->next = insertNode; std::cout<<"【NOTICE】请输入下一个结点数据域的数据"<<std::endl; std::cin>>insertData; }//while return pHead; } /************************************************************************************************************************* 函数原型: LinkList CreatListTail(LinkList& pHead) 函数说明: 【1】尾插法建立单链表。 【2】该方法是将新结点插入到当前链表的表尾,为此,必须增加一个尾指针r,使其始终指向当前链表的尾结点。 **************************************************************************************************************************/ LinkList CreatListTail(LinkList& pHead) { int insertData = 0; //【1】设单链表元素的类型为整形 LNode* insertNode = NULL; LNode* pTail = NULL; pTail = pHead; //【3】让表尾指针指向头结点 std::cout<<"【NOTICE】请输入单链表第一个要插入结点的数据insertData"<<std::endl; std::cin>>insertData; //【4】输入结点的值 while(insertData!=9999) { insertNode = (LNode*)std::malloc(sizeof(LNode)); insertNode->data = insertData; pTail->next = insertNode; pTail = insertNode; std::cout<<"【NOTICE】请输入下一个结点数据域的数据"<<std::endl; std::cin>>insertData; }//while pTail->next = NULL; return pHead; } /************************************************************************************************************************* 函数原型: void PrintList(LinkList pHead) 函数说明: 打印单链表,单链表的遍历 **************************************************************************************************************************/ void PrintList(LinkList pHead) { LNode* pTemp = NULL; pTemp = pHead->next; if(pHead->next==NULL) { std::cout<<"【NOTICE】PrintList函数被执行,但是单链表为一个空链表!"<<std::endl; } else { std::cout<<"【NOTICE】单链表中存储的数据如下所示:"<<std::endl; while(pTemp) { std::cout<<pTemp->data<<std::endl; pTemp = pTemp->next; } } }//void /************************************************************************************************************************* 函数原型: void CleanList(LinkList pHead) 函数说明: 清除线性表中的所有元素,即释放单链表pHead中所有的结点,使之成为一个空表。 **************************************************************************************************************************/ void CleanList(LinkList& pHead) { LNode* pNext = NULL; LNode* pTemp = NULL; pTemp = pHead->next; if(pHead->next==NULL) { std::cout<<"【NOTICE】CleanList函数执行,链表为空!"<<std::endl; } while (pTemp!=NULL) { pNext = pTemp->next; //【1】保存下一个结点的指针 std::free(pTemp); pTemp = pNext; //【2】表头后移 } std::cout<<"【NOTICE】CleanList函数执行完毕,链表已经清除!"<<std::endl; pHead->next = NULL; }//void /************************************************************************************************************************* 函数原型: int SizeList(LinkList pHead) 函数说明: 返回单链表的实际长度 **************************************************************************************************************************/ int SizeList(LinkList pHead) { int iSize = 0; LNode* pTemp = NULL; pTemp = pHead->next; while (pTemp!=NULL) { iSize++; pTemp = pTemp->next; } std::cout<<"【NOTICE】SizeList函数已经执行,链表的长度为 = "<<iSize<<std::endl; return iSize; } /************************************************************************************************************************* 函数原型: bool isEmptyList(LNode* pHead) 函数说明: 检查单链表是否为空,若为空,则返回1,否则返回0 **************************************************************************************************************************/ bool IsEmpty(LinkList pHead) { LNode* pTemp = NULL; pTemp = pHead->next; if(pHead->next==NULL) { std::cout<<"【NOTICE】IsEmpty函数执行成功,链表为空!"<<std::endl; return true; } else { std::cout<<"【NOTICE】IsEmpty函数执行成功,链表非空!"<<std::endl; return false; } } /************************************************************************************************************************* 函数原型: LNode* GetElement(LinkList pHead,int i) 函数说明: 【1】按序号查找结点值 【2】在单链表中从第一个结点出发,顺着指针域逐个往下搜索,直到找到第i个结点为止,否则返回最后一个结点指针域NULL 【3】本算法取出单链表L(带头结点)中第i个位置的结点指针 **************************************************************************************************************************/ LNode* GetElement(LinkList pHead,int iPos) { int iCount = 0; LNode* pTemp = NULL; pTemp = pHead->next; if(iPos<1) //【1】位置合法性检查 { std::cout<<"【NOTICE】GetElement函数执行成功,iPos位置非法!"<<std::endl; std::system("pause"); std::exit(1); } if(pHead->next==NULL) //【2】单链表是否为空 { std::cout<<"【NOTICE】GetElement函数执行成功,链表为空!"<<std::endl; std::system("pause"); std::exit(1); } while (pTemp!=NULL) { ++iCount; if(iCount==iPos) { break; } pTemp = pTemp->next; } if(iCount<iPos) { std::cout<<"【NOTICE】GetElement函数执行成功,iPos值超出链表长度!"<<std::endl; std::system("pause"); std::exit(1); } return pTemp; } /************************************************************************************************************************* 函数原型: LNode* LocateElem(LinkList pHead,ElemType x) 函数说明: 【1】按值查找表结点 【2】从单链表第一个结点开始,由前往后依次比较表中各结点数据域的值,,若某结点数据域的值相等,则返回该节点的指针。 若整个单链表中没有这样的结点,则返回NULL. **************************************************************************************************************************/ LNode* LocateElem(LinkList pHead,ElemType x) { LNode* pTemp = NULL; pTemp = pHead->next; if(pHead->next == NULL) { std::cout<<"【NOTICE】LocateElem函数执行完毕,链表为空!"<<std::endl; std::system("pause"); return NULL; } while((pTemp->data!=x)&&(pTemp!=NULL)) { pTemp = pTemp->next; } if((pTemp->data!=x)&&(pTemp->next==NULL)) { std::cout<<"【NOTICE】LocateElem函数执行完毕,在链表中没有找到X值!!"<<std::endl; std::system("pause"); std::exit(1); } return pTemp; } /************************************************************************************************************************* 函数原型: bool InsertList(LinkList& pHead,int i,ElemType x) 函数说明: 【1】插入结点操作 【2】插入操作是将值为X的新结点插入到单链表pHead的第i个位置上。 【3】插入操作的步骤: (1)先检查插入位置的合法性 (2)找到待插入位置的前驱结点,即第i-1个结点 (3)再在其后插入位置的新结点。 **************************************************************************************************************************/ bool InsertList(LinkList& pHead,int iPos,ElemType x) { if(iPos<1) { std::cout<<"【NOTICE】InsertList函数被执行,但是元素插入的位置不合法!"<<std::endl; std::system("pause"); return false; } LNode* pTemp = NULL; LNode* pInsertNode = NULL; pInsertNode = (LNode*)std::malloc(sizeof(LNode)); pInsertNode->data = x; pTemp = GetElement(pHead,iPos-1); pInsertNode->next = pTemp->next; pTemp->next = pInsertNode; std::cout<<"【NOTICE】InsertList函数被执行,插入成功!"<<std::endl; return true; } /************************************************************************************************************************* 函数原型: bool DeleteList(LinkList& pHead,int iPos) 函数说明: 【1】删除结点操作 【2】删除结点操作是将单链表pHead的第i个位置上的结点删除 【3】删除操作的步骤: (1)先检查删除位置的合法性 (2)然后查找表中第iPos-1个结点,即被删除结点的前驱结点 (3)再将其删除 **************************************************************************************************************************/ bool DeleteList(LinkList& pHead,int iPos) { if(iPos<1) { std::cout<<"【NOTICE】DeleteList函数被执行,但是删除元素的位置不合法!"<<std::endl; std::system("pause"); return false; } LNode* pTemp = NULL; LNode* pDelete= NULL; pTemp = GetElement(pHead,iPos-1); pDelete= GetElement(pHead,iPos); pTemp->next = pDelete->next; std::free(pDelete); std::cout<<"【NOTICE】DeleteList函数被执行,删除成功!"<<std::endl; return true; } int main() { LinkList pHead = NULL; LinkList pTail = NULL; int iLength = 0; ElemType posElem; InitList(pHead); PrintList(pHead); CreatListHead(pHead); PrintList(pHead); InitList(pTail); CreatListTail(pTail); PrintList(pTail); LNode* pValue = NULL; pValue = GetElement(pTail,2); std::cout<<"【NOTICE】单链表中的第二个元素的值 = "<<pValue->data<<std::endl; SizeList(pTail); bool flagEmpty = true; flagEmpty = IsEmpty(pTail); if(flagEmpty) { std::cout<<"【NOTICE】单链表为空表!"<<std::endl; } else { std::cout<<"【NOTICE】单链表不为空!"<<std::endl; } LNode* pData = NULL; pData = LocateElem(pTail,2); std::cout<<"【NOTICE】查找出来的值 = "<<pData->data<<std::endl; InsertList(pTail,2,8888); PrintList(pTail); CleanList(pTail); PrintList(pTail); SizeList(pTail); std::system("pause"); return 0; }
相关文章推荐
- 【Data_Structure笔记1】线性表的顺序存储【顺序表】
- 数据结构之线性表——链表的链式存储(链式描述)
- 数据结构之线性表——链表的链式存储(链式描述)
- C语言单链表(线性表的链式存储)的实现
- 线性表的链式存储(单链表)C语言实现
- 数据结构与算法(二)-线性表之单链表顺序存储和链式存储
- 结构之美:线性表的链式存储结构——链表
- 【数据结构复习】线性表的链式存储--单链表
- 线性表链式存储(单链表)
- 线性表的链式存储结构-单链表
- 数据结构:线性表的链式存储(单向链表)--Java实现
- 结构之美:线性表的链式存储结构——链表
- 数据结构之线性表——链表的链式存储(链式描述)注释版
- 线性表的Java实现--链式存储(单向链表)
- 线性表的链式存储(单链表)的c语言实现
- 03.线性表(二)链式存储结构.单链表1
- <<C#版数据结构>>之--线性表的链式存储(单链表)
- 2.3_线性表的链式存储结构_单链表
- 线性表的链式存储——链表(带源码)
- 线性表的链式存储格式基本操作:创建链表、插入、删除、查找、求表长、打印链表