【Data_Structure笔记2】线性表的链式存储【单链表】

来源:互联网 发布:js秒杀脚本 编辑:程序博客网 时间:2024/06/06 02:40
/************************************************************************************************************************文件说明:        线性表的链式存储之【单链表】、【双链表】、【循环链表】、【静态链表】详细说明:        【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;}//whilereturn 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;}//whilepTail->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;}