链表:也是线性表的一种。形象的来说:
就像火车的一个个车厢一样,一个个的链起来的。它有一个特点:它的头没有前驱,尾没有后继。
为什么会引入链表这个概念呢?之前我们知道的顺序表,是用数组的形式保存数据的。它使用起来也非常方便,优点在于它的尾删尾插非常方便,直接将数组空间大小加1,给最后一个数组赋值就ok了。但是对于数组来说,也有一定的缺点。比如:如果在中间插入或删除的话,就得移动一定得位数才可进行相关操作。最坏得情况是你在头插头删的时候,时间的消耗更巨大。为了避免这种重复的移位操作,我们引入了链表这个概念。链表的头插头删就容易多了,只需修改头节点的位置就好啦。
链表的种类很多,有单链表、双向链表、循环链表等。今天我们主要讲单链表。
那么链表的结构是怎么样的呢?
typedef int DataType;
struct Node
{
DataType data; //节点里存放的数据
struct Node* next; //指向下一个节点的指针
};
下面我们来一一实现它们吧~
//SList.h
#pragma once
#include<iostream>
using namespace std;
typedef int DataType;
typedef struct Node
{
int data;
struct Node* next;
}Node,*pNode;
void InitSlist(pNode *pHead);
void PushBack(pNode *pHead,DataType data);
void PopBack(pNode *pHead);
void PushFront(pNode *pHead,DataType data);
void PopFront(pNode *pHead);
pNode BuyNode(DataType data);
pNode Find(pNode pHead, DataType data);
void Insert(pNode pos, DataType data); //某个位置插入data
void Erase(pNode* pHead, pNode pos); //删除位置节点
void Remove(pNode* pHead, DataType data); //删除某个数据的节点
void RemoveAll(pNode* pHead, DataType data); //删除所有数据为data的节点
void Destroy(pNode* pHead); //销毁
int Empty(pNode pHead); //判空
int Size(pNode pHead); //节点数目
//SList.cpp
#include"SList.h"
#include<assert.h>
void InitSlist(pNode *pHead)
{
*pHead = NULL;
}
pNode BuyNode(DataType data) //创建一个新节点
{
pNode newNode = (pNode)malloc(sizeof(Node));
assert(newNode);
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void PushBack(pNode *pHead,DataType data)
{
if(*pHead == NULL)
{
*pHead = BuyNode(data);
(*pHead)->next = NULL;
}
else
{
pNode pCur = *pHead;
while(pCur->next)
{
pCur = pCur->next;
}
pCur->next = BuyNode(data);
}
}
void PopBack(pNode *pHead)
{
if(*pHead == NULL)
return;
if((*pHead)->next == NULL)
{
free(*pHead);
*pHead = NULL;
}
else
{
pNode pCur = *pHead;
pNode pPrev = NULL;
while(pCur->next)
{
pPrev = pCur;
pCur = pCur->next;
}
free(pCur);
pPrev->next = NULL;
}
}
void PushFront(pNode *pHead,DataType data)
{
if(*pHead == NULL)
*pHead = BuyNode(data);
else
{
pNode cur = BuyNode(data);
cur->next = *pHead;
*pHead = cur;
}
}
void PopFront(pNode *pHead)
{
if(*pHead == NULL)
return;
else
{
pNode pDel = *pHead;
*pHead = (*pHead)->next;
free(pDel);
}
}
pNode Find(pNode pHead, DataType data)
{
pNode pCur = pHead;
while(pCur)
{
if(pCur->data == data)
{
return pCur;
}
pCur = pCur->next;
}
return NULL;
}
void Insert(pNode pos, DataType data)
{
pNode newNode = BuyNode(data);
if(pos == NULL)
return;
newNode->next = pos->next;
pos->next = newNode;
}
void Erase(pNode* pHead, pNode pos)
{
pNode pCur = *pHead;
if(*pHead == pos && (*pHead)->next == NULL)
{
free(pos);
*pHead = NULL;
return;
}
while(pCur)
{
pNode pPrev = pCur;
while(pPrev->next == pos)
{
pNode pDel = pos;
pPrev->next = pos->next;
free(pDel);
return;
}
pCur = pCur->next;
}
return;
}
void Remove(pNode* pHead, DataType data)
{
pNode pos = Find(*pHead,data);
Erase(pHead,pos);
}
void Destroy(pNode* pHead)
{
while(*pHead)
{
pNode pDel = *pHead;
*pHead = (*pHead)->next;
free(pDel);
}
return;
}
int Empty(pNode pHead)
{
return pHead == NULL;
}
int Size(pNode pHead)
{
pNode pCur = pHead;
int count = 0;
if(pHead == NULL)
return 0;
while(pCur)
{
count++;
pCur = pCur->next;
}
return count;
}
void Print(pNode pHead)
{
pNode pCur = pHead;
while(pCur)
{
cout<<pCur->data<<"->";
pCur = pCur->next;
}
cout<<"NULL"<<endl;
}
对于单链表,我们还有一些有趣的题来和大家分享哦。