一、什么是链表,链表的分类?
·链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
·八种链表结构:
1,单向、双向
2,带头、不带头
3,循环、非循环
常用的有: 1,无头单向非循环链:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构
2,带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。
二、链表带头结点和不带头结点的区别?
所有的链表都有一个头指针head,带头结点的链表中head的数据项为空,而不带头的链表直接在头结点存入数据,那么当从头插入数据时,head需要时刻变化。带头结点的单链表,不论删除和插入的位置如何,不需要修改head的值,不带头结点的单链表当头插和头删需要修改head的值。所以一般单链表一般带有头结点。
三、单链表的以下基本操作:
typedef int SDataType;
// 链表的节点
typedef struct SListNode
{
SDataType _data;
struct SListNode* _pNext;
}Node, *PNode;
// 链表的结构,给一个头指针保存链表第一个节点的地址
typedef struct SList
{
PNode _pHead; // 指向链表中的第一个节点
}SList, *PSList;
// 链表的初始化
void SListInit(SList* s);
{
assert(s);
s->_Phead = NULL;
}
PNode BuySListNode(SDataType data)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
if (NULL == pNewNode)
{
assert(0);
return NULL;
}
pNewNode->_data = data;
pNewNode->_pNext = NULL;
return pNewNode;
}
// 在链表s最后一个节点后插入值为data的节点
void SListPushBack(SList* s, SDataType data);
{
assert(s);
PNode pNewNode = BuySListNode(data);
if (NULL == s->_pHead)
{
//空链表
s->_pHead = pNewNode;
}
else
{
//链表非空,找链表最后一个节点
PNode pCur = s->_pHead;
while(pCur->_pNext)
pCur = pCur->_pNext;
pCur->_pNext = pNewNode;
}
}
// 删除链表s最后一个节点
void SListPopBack(SList* s);
assert(s);
if(NULL == s->_pHead) //空链表
return;
else if (NULL == s->_pHead->_pNext) // 只有一个节点
{
free(s->_pHead);
s->_pHead = NULL;
}
else
{
//多个节点
PNode pPre = NULL;
PNode pCur = s-_pHead;
while(pCur->_pNext)
{
pPre = pCur;
pCur = pCur->pNext;
}
free(pCur);
pPre->_pNext = NULL;
}
}
// 在链表s第一个节点前插入值为data的节点
void SListPushFront(SList* s, SDataType data);
{
assert(s);
PNode pNewNode = BuySListNode(data);
pNewNode->_pNext = s->_pHead;
s->_pHead = pNewNode;
}
// 删除链表s的第一个节点
void SListPopFront(SList* s);
{
PNode pDelNode = NULL;
assert(s);
if(NULL == s->_pHead)
return;
//找到待删除的节点
pDelNode = s->_pHead;
s->_pHead = pDelNode->_pNext;
free(pDelNode);
}
// 在链表的pos位置后插入值为data的节点
void SListInsert(PNode pos, SDataType data);
{
PNode pNewNode = NULL;
if(NULL == pos)
return;
pNewNode = BuySListNode(data);
pNewNode->_pNext = pos->_pNext;
pos->_pNext = pNewNode;
}
// 删除链表s中pos位置的节点
void SListErase(SList* s, PNode pos);
{
assert(s);
if(NULL == pos || NULL == s->_pHead)
return;
if(pos == s->_pHead)
{
s->_pHead = pos->_pNext;
}
else
{
PNode pPrePos = s->_pHead;
while(pPrePos && pPrePos->_pNext != pos)
pPrePos = pPrePos->_pNext;
if(pPrePos)
pPrePos->_pNext = pos->_pNext;
}
free(pos);
}
// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL
PNode SListFind(SList* s, SDataType data);
{
assert(s);
PNode pCur = s->_pHead;
while(pCur)
{
if(pCur->_data == data)
return pCur;
pCur = pCur->_pNext;
}
return NULL;
}
// 获取链表中有效节点的个数
size_t SListSize(SList* s);
{
assert(s);
PNode pCur = s->_pHead;
size_t count = 0;
while(pCur)
{
count++;
pCur = pCur->_pNext;
}
return conut;
}
// 检测链表是否为空
int SListEmpty(SList* s);
{
assert(s);
return NULL == s->_pHead;
}
// 将链表中有效节点清空
void SListClear(SList* s);
{
assert(s);
if(NULL == s->_pHead)
return;
PNode pPre = NULL;
PNode pCur = s->_pHead;
while(pCur)
{
if (pCur->_data == data)
{
if (pCur == s->_pHead)
{
s->_pHead = pCur->_pNext;
}
else
{
pPre->_pNext = pCur->_pNext;
}
free(pCur);
return;
}
else
{
pPre = pCur;
pCur = pCur->_pNext;
}
}
}
// 销毁链表
void SListDestroy(SList* s);
{
if(pCur->NULL)
{
free(pCur);
}
}