1.熟悉什么是链表,链表的分类?
概念:链表是一种在物理内存上不连续的数据结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
分类:
- 单向、双向
- 带头、不带头
- 循环、不循环
一共有2³=8种组合,最常见有无头单向不循环链表和带头双向循环链表。
2.熟悉链表带头结点和不带头结点的区别?
带头结点的优点:
更快删除/插入第一个结点
统一空表和非空表的处理
3.单链表的一些基本操作:
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
typedef int SDataType;
typedef struct SListNode
{
SDataType data;
struct SListNode* next;
}Node, *PNode;
typedef struct SList
{
PNode head;
}SList,*PSlist;
void SListInit(SList* s)//初始化
{
assert(s);
s->head = NULL;
}
PNode BuySListNode(SDataType data)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
if (NULL == pNewNode)
{
assert(0);
return NULL;
}
pNewNode->data = data;
pNewNode->next = NULL;
return pNewNode;
}
void SListPushBack(SList* s, SDataType data)// 在链表s最后一个节点后插入值为data的节点
{
assert(s);
PNode pNewNode = BuySListNode(data);
if (NULL == s->head)
{
s->head = pNewNode;
}
else
{
PNode pCur = s->head;
while (pCur->next)
{
pCur = pCur->next;
}
pCur->next = pNewNode;
}
}
void SListPopBack(SList* s)// 删除链表s最后一个节点
{
assert(s);
if (NULL == s->head)
{
return;
}
else if (NULL == s->head->next)
{
free(s->head);
s->head = NULL;
}
else
{
PNode pCur = s->head->next;
PNode pPre = s->head;
while (pCur->next)
{
pCur = pCur->next;
pPre = pPre->next;
}
free(pCur);
pPre->next = NULL;
}
}
void SListPushFront(SList* s, SDataType data)//在链表s第一个节点前插入值为data的节点
{
assert(s);
PNode pNewNode = BuySListNode(data);
pNewNode->next = s->head;
s->head = pNewNode;
}
void SListPopFront(SList* s)// 删除链表s的第一个节点
{
PNode pDelNode = NULL;
assert(s);
if (NULL == s->head)
return;
pDelNode = s->head;
s->head = pDelNode->next;
free(pDelNode);
}
void SListInsert(PNode pos, SDataType data)// 在链表的pos位置后插入值为data的节点
{
PNode pNewNode = BuySListNode(data);
if (NULL == pos)
return 0;
pNewNode->next = pos->next;
pos->next=pNewNode;
}
void SListErase(SList* s, PNode pos)// 删除链表s中pos位置的节点
{
assert(s);
if (NULL == s->head||pos==NULL)
return;
if (pos == s->head)
s->head = pos->next;
else
{
PNode pCur = s->head;
while (pCur->next != pos)
{
pCur = pCur->next;
}
pCur->next = pos->next;
free(pos);
}
}
size_t SListSize(SList* s)// 获取链表中有效节点的个数
{
assert(s);
PNode pCur = s->head;
size_t count = 0;
while (pCur)
{
count++;
pCur = pCur->next;
}
return count;
}
int SListEmpty(SList* s)// 检测链表是否为空
{
assert(s);
if (s->head == NULL)
return NULL;
}
void SListClear(SList* s)// 将链表中有效节点清空
{
assert(s);
PNode pCur = s->head;
while (pCur)
{
pCur->data = NULL;
pCur = pCur->next;
}
}
void SListDestroy(SList* s)// 销毁链表
{
PNode pCur = s->head;
PNode pNext = pCur->next;
while (pNext)
{
free(pCur);
pCur = pNext;
pNext = pCur->next;
}
}
PNode SListfind(SList* s, SDataType data)//在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL
{
assert(s);
PNode pCur = s->head;
while (pCur)
{
if (pCur->data == data)
return pCur;
pCur = pCur->next;
}
return NULL;
}
void PrintfSList(SList* s)//打印链表
{
assert(s);
PNode pCur = s->head;
while (pCur)
{
printf("%d--->", pCur->data);
pCur = pCur->next;
}
printf("NULL\n");
}
int main(void)
{
SList s;
SList* p = NULL;
SListInit(&s);
printf("初始化\n");
PrintfSList(&s);
printf("尾插\n");
SListPushBack(&s, 5);
PrintfSList(&s);
printf("尾插\n");
SListPushBack(&s, 4);
PrintfSList(&s);
printf("头插\n");
SListPushFront(&s, 3);
PrintfSList(&s);
printf("pos后加data\n");
SListInsert(SListfind(&s,5), 1);
PrintfSList(&s);
printf("删除pos\n");
SListErase(&s, SListfind(&s, 4));
PrintfSList(&s);
printf("头删\n");
SListPopFront(&s);
PrintfSList(&s);
printf("尾删\n");
SListPopBack(&s);
PrintfSList(&s);
printf("有效节点%d\n",SListSize(&s));
printf("清空链表\n");
SListClear(&s);
PrintfSList(&s);
SListDestroy(&s);
system("pause");
return 0;
}