1、链表的概念:链表是一种非连续、非顺序的数据结构。
2、链表的分类:主要分为这三类:单链表、双向链表、循环链表,这三者又可以通过组合形成总共8种链表。
3、链表的基本操作:
// 动态链表的基本操作:
//不带头节点的单链表
typedef int SDataType;
// 节点结构
typedef struct SListNode
{
SDataType _data;
struct SListNode* _pNext;
}Node;
// 给一个链表结构
typedef struct SList
{
Node* _pHead;
}SList;
// 链表的初始化
void SListInit(SList* pl){
assert(pl);
pl->_pHead = NULL;
}
// 在链表中尾插值为data的节点
void SListPushBack(SList* pl, SDataType data){
assert(pl);
Node* node = (Node*)malloc(sizeof(Node));
node->_data = data;
// 如果链表中只有一个结点
if (pl->_pHead == NULL){
node->_pNext = NULL;
pl->_pHead = node;
return;
}
// 不止一个结点,先找到最后一个结点
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
cur = cur->_pNext;
}
cur->_pNext = node;
}
// 删除链表最后一个节点
void SListPopBack(SList* pl){
assert(pl);
// 只有一个结点
if (pl->_pHead->_pNext == NULL){
free(pl->_pHead);
pl->_pHead == NULL;
}
// 不止一个结点
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
cur = cur->_pNext;
}
free(cur->_pNext);
cur->_pNext = NULL;
}
// 在链表第一个元素前插入值为data的节点 (头插)
void SListPushFront(SList* pl, SDataType data){
assert(pl);
Node* node = (Node*)malloc(sizeof(Node));
node->_data = data;
node->_pNext = pl->_pHead;
pl->_pHead = node;
}
// 删除链表中第一个节点
void SListPopFront(SList* pl){
assert(pl);
Node* next = pl->_pHead->_pNext;
free(pl->_pHead);
pl->_pHead == next;
}
// 在链表pos位置后插入置为data的节点
void SListInsertAfter(Node* pos, SDataType data){
Node* node = (Node*)malloc(sizeof(Node));
node->_data = data;
node->_pNext = pos->_pNext;
pos->_pNext = node;
}
// 删除pos后的结点
void SListEraseAfter(SListNode* pos){
Node* cur = pos->_pNext;
pos->_pNext = pos->_pNext->_pNext;
free(pos->_pNext);
free(cur);
}
// 删除链表中值为data的节点
void SListErase(SList* pl, SDataType data){
// 链表为空
if (pl == NULL){
return;
}
// 是链表的第一个结点
if (pl->_pHead->_data == data){
Node* next = pl->_pHead->_pNext;
free(pl->_pHead);
pl->_pHead = next;
return;
}
// 遍历
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
if (cur->_pNext->_data == data){
Node* next = cur->_pNext->_pNext;
free(cur->_pNext);
cur->_pNext = next;
}
cur = cur->_pNext;
}
}
// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回空
Node* SListFind(SList* pl, SDataType data){
if (pl == NULL){
return NULL;
}
if (pl->_pHead->_data == data){
return pl->_pHead;
}
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
if (cur->_pNext->_data == data){
return cur->_pNext;
cur = cur->_pNext;
}
}
return NULL;
}
// 销毁链表
void SListDestroy(SList* pl){
// 删除所有结点
Node* cur = pl->_pHead;
Node* next = cur->_pNext;
while (cur->_pNext != NULL){
next = cur->_pNext;
free(cur);
}
pl->_pHead = NULL;
}
// 获取链表中有效节点的个数
int SListSize(SList* pl){
int count = 0;
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
cur = cur->_pNext;
count++;
}
return count;
}
// 检测链表是否为空
int SListEmpty(SList* pl){
if (pl->_pHead == NULL){
return 1;
}
else
return 0;
}
// 获取链表的第一个节点
Node* SListFront(SList* pl){
assert(pl);
return pl->_pHead;
}
// 获取链表的第二个节点
Node* SListBack(SList* pl){
assert(pl);
return pl->_pHead->_pNext;
}
// 删除链表中第一个值为data的节点
void SListRemove(SList* pl, SDataType data){
assert(pl);
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
if (cur->_pNext->_data == data){
Node* next = cur->_pNext->_pNext;
free(cur->_pNext);
cur = next;
break;
}
}
}
// 删除链表中所有值为data的节点
void SListRemoveAll(SList* pl, SDataType data){
assert(pl);
Node* cur = pl->_pHead;
while (cur->_pNext != NULL){
if (cur->_pNext->_data == data){
Node* next = cur->_pNext->_pNext;
free(cur->_pNext);
cur = next;
}
}
}
// 熟悉双向链表的结构,并实现带头结点的双向循环链表的以下基本操作:
typedef int DLDataType;
typedef struct DListNode
{
struct DListNode* _pNext;
struct DListNode* _pPre;
DLDataType _data;
}DLNode;
// 初始化双向链表
void DListInit(DLNode* pHead){
assert(pHead);
pHead->_pNext = NULL;
pHead->_pPre = NULL;
}
// 尾插
void DListPushBack(DLNode* pHead, DLDataType data){
assert(pHead);
DLNode* node = (DLNode*)malloc(sizeof(DLNode));
node->_data = data;
node->_pNext = pHead;
node->_pPre = pHead->_pPre;
pHead->_pPre->_pNext = node;
pHead->_pPre = node;
}
// 尾删
void DListPopBack(DLNode* pHead){
assert(pHead);
if (pHead->_pNext = pHead){
return;
}
else{
pHead->_pPre = pHead->_pPre->_pPre;
free(pHead->_pPre->_pNext);
pHead->_pPre->_pNext = pHead;
}
}
// 头插
void DListPushFront(DLNode* pHead, DLDataType data){
assert(pHead);
DLNode* node = (DLNode*)malloc(sizeof(DLNode));
node->_data = data;
node->_pNext = pHead->_pNext;
node->_pPre = pHead;
pHead->_pNext->_pPre = node;
pHead->_pNext = node;
}
// 头删
void DListPopFront(DLNode* pHead){
assert(pHead);
DLNode* cur = pHead->_pNext;
pHead->_pNext->_pNext->_pPre = pHead;
pHead->_pNext = pHead->_pNext->_pNext;
free(cur);
cur = NULL;
}
// 在链表中查找值为data的节点,找到返回节点的位置
DLNode* DListFind(DLNode* pHead, DLDataType data){
assert(pHead);
DLNode* cur = pHead->_pNext;
while (cur != pHead){
if (cur->_data == data){
return cur;
}
cur = cur->_pNext;
}
return NULL;
}
// 在pos位置(插入成功后新节点实际在pos前)插入值为data的元素
void DListInsert(DLNode* pos, DLDataType data){
assert(pos);
DLNode* node = (DLNode*)malloc(sizeof(DLNode));
node->_data = data;
node->_pNext = pos;
node->_pPre = pos->_pPre;
pos->_pPre->_pNext = node;
pos->_pPre = node;
}
// 删除pos位置的节点
void DListErase(DLNode* pos){
assert(pos);
pos->_pNext->_pPre = pos->_pNext;
pos->_pPre->_pNext = pos->_pPre;
free(pos);
pos = NULL;
}
// 将链表中的所有节点清空
void DListClear(DLNode* pHead){
assert(pHead);
DLNode* cur = pHead->_pNext;
while (cur != pHead){
DLNode* next = cur->_pNext;
cur->_pNext->_pPre = cur->_pPre;
cur->_pPre->_pNext = cur->_pNext;
free(cur);
cur = next->_pNext;
}
}
// 销毁链表
void DListDestroy(DLNode** pHead){
assert(pHead);
DLNode* cur = *pHead;
cur = cur->_pNext;
while (cur != *pHead)
{
DLNode* next = cur->_pNext;
free(next);
}
free(*pHead);
*pHead = NULL;
}