【数据结构】单向链表的相关操作
1、相关定义
线性表的链式存储
解决顺序存储的缺点,插入和删除,动态存储问题。
特点
线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素,存储单元可以是连续的,也可以不连续。可以被存储在任意内存未被占用的位置上。所以前面的顺序表只需要存储数据元素信息就可以了。在链式结构中还需要一个元素存储下一个元素的地址。为了表示每个数据元素,ai与其直接后继数据元素ai+1之间的逻辑关系,对ai来说,除了存储其本身的信息外,还需要存一个指示器直接后续的信息。把存储元素信息的域叫数据域,把存储直接后继位置的域叫指针域。这两部分信息组成数据元素ai的存储映像,叫结点(Node);
2、单向链表的相关操作和图解
1、单向链表的C语言描述
/*存储的数据类型*/
typedef int DataType;
/*结点类型*/
typedef struct node
{
DataType Data; //数据域
struct node *pNext; //指针域
}LinkNode;
/*标签类型*/
typedef struct list{
LinkNode *pHead; //头节点指针
int cLen; //节点个数
}LinkList;
2、链表的相关操作
-
链表的创建
原理如图所示:
LinkList *creatLinkList()
{
LinkList *pList = malloc(sizeof(LinkList));
if (NULL == pList)
{
perror("fail to malloc");
return NULL;
}
pList->pHead = NULL;
pList->cLen = 0;
return pList;
}
int IsEmpty(LinkList *pList)//判空函数
{
return pList->cLen == 0;
}
-
链表的插入(头插与尾插)
原理如图所示:
int insertHeadLinkList(LinkList *pList,DataType Data)//链表的头插
{
LinkNode *pInsertNode = malloc(sizeof(LinkNode));
if (NULL == pInsertNode)//判断是否malloc成功
{
perror("fail to malloc");
return -1;
}
pInsertNode->Data = Data;
pInsertNode->pNext = pList->pHead;
pList->pHead = pInsertNode;
pList->cLen++;
return 0;
}
int insertTailLinkList(LinkList *pList,DataType Data) //链表的头插(待验证)
{
LinkNode * pTmpNode = pList->pHead;
LinkNode * pInsertNode = malloc(sizeof(LinkNode));
if (NULL == pInsertNode)
{
perror("fail to malloc");
return -1;
}
pInsertNode->pNext= NULL;
while(pTmpNode->pNext !=NULL) //先用临时指针遍历到链表的末尾
{
pTmpNode = pTmpNode->pNext ;
}
pTmpNode->pNext = pInsertNode ;
pList->cLen++;
return 0;
}
- 链表的删除 (头删与尾删)
int deleteTailLinkList(LinkList *pList)//链表的尾删
{
if (isEmptyLinkList(pList))//先判定链表是否为空,如果为空,就退出删除链表操作
{
return 0;
}
else if (pList->cLen == 1)//如果只有一个节点,就采取头删操作
{
deleteHeadLinkList(pList);
}
else
{
LinkNode *pTmpNode = pList->pHead; //开辟一个临时指针指向头结点
while (pTmpNode->pNext->pNext != NULL)//将临时指针指向倒数第二个指针
{
pTmpNode = pTmpNode->pNext;
}
free(pTmpNode->pNext);//free最后一个节点
pTmpNode->pNext = NULL;
pList->cLen--;
}
return 0;
}
int deleteHeadLinkList(LinkList *pList)//链表的头删
{
if (isEmptyLinkList(pList))//先判定链表是否为空,如果为空,就退出删除链表操作
{
return 0;
}
LinkNode * pTmpNode =pList->Phead ;// 定义一个临时指针指向头结点
pTmpNode->pNext = pList->Phead; //把标签的head指针指向第二个节点
free(pTmpNode);//把第一个节点free掉
return 0 ;
}
- 链表的查找
LinkNode *findNodeLinkList(LinkList *pList,DataType data)
{
LinkNode *pFindNode = pList->pHead;// 定义一个pFindNode指针指向头结点
while (pFindNode != NULL)//用pFindNode向后遍历
{
if (pFindNode->Data == data)//如果发现待查找的节点
{
return pFindNode;//将该节点返回
}
pFindNode = pFindNode->pNext;
}
return NULL;
}
-
链表的修改
查到需要修改的节点,修改他的值
int modifyNodeLinkList(LinkList *pList,DataType oldData,DataType newData)
{
LinkNode *pFindNode = NULL;
if ((pFindNode = findNodeLinkList(pList,oldData)) != NULL)
{
pFindNode->Data = newData;
return 0;
}
else
{
return -1;
}
}