熟悉什么是链表,链表的分类?
链表是一种物理储存上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序来实现的
链表分为:1.单向,双向2.带头,不带头3.循环和非循环,组合起来总共八种
熟悉链表带头结点和不带头结点的区别?
使用头结点,则第1个位置的插入和删除都是对p—>next进行操作,而不用动p本身,而且减少了算法分支
代码示例:
Slist.h
typedef int SLTDatatype;
typedef struct SListNode
{
SLTDatatype _data;
struct SListNode* _Next;
}Node,*PNode;
typedef struct SList
{
Node* _Head;
}SList;
void SListInit(SList* s);
void SListDestroy(SList* s);
Node* BuySListNode(SLTDatatype data);
void SListPushFront(SList* s,SLTDatatype data);
void SListPopFront(SList* s);
void SListPushBack(SList* s,SLTDatatype data);
void SListPopBack(SList* s);
Node* SListFind(SList* s,SLTDatatype data);
Node* SListFindPos(SList* s, SLTDatatype data);
void SListInsertAfter(PNode pos,SLTDatatype data);
void SListEraseAfter(PNode pos);
void SListRemove(SList* s, SLTDatatype data);
size_t SListSize(SList* s);
int SListEmpty(SList* s);
void SListClear(SList* s);
Test.c
#include"Slist.h"
#include<stdio.h>
#include<stdlib.h>
#include <assert.h>
//初始化操作
void SListInit(SList* s)
{
assert(s);
s->_Head = NULL;
}
//销毁
void SListDestroy(SList* s)
{
assert(s);
PNode pCur = s->_Head;
while (pCur!= NULL)
{
pCur = pCur->_Next;
free(pCur);
}
s->_Head = NULL;
}
//创建新的节点
Node* BuySListNode(SLTDatatype data)
{
PNode node = (PNode*)malloc(sizeof(Node));//给新节点申请内存空间
assert(node);//检验申请的空间是否成功
node->_data = data;
node->_Next = NULL;//把相应的数据存到节点内
return node;
}
//头插
void SListPushFront(SList* s,SLTDatatype data)
{
assert(s);
PNode node=BuySListNode(data);
assert(node);
node->_Next = s->_Head;//顺序不能颠倒,否则会破坏链表结构丢失数据
s->_Head = node;
}
//头删
void SListPopFront(SList* s)
{
assert(s);
assert(s != NULL);
s->_Head = s->_Head->_Next;
}
//尾插
void SListPushBack(SList* s,SLTDatatype data)
{
assert(s);
PNode node = BuySListNode(data);
node->_Next = NULL;
PNode pCur = s->_Head;
while (pCur->_Next!=NULL)
{
pCur = pCur->_Next;
}
pCur->_Next = node;
}
//尾删
void SListPopBack(SList* s)
{
assert(s);
if (s->_Head->_Next == NULL)//只有一个节点
{
SListPopFront(&s);
}
PNode pCur = s->_Head;
while (pCur->_Next->_Next != NULL)//pcur的下一个节点的next指向空,说明pcur是倒数第二个
{
pCur = pCur->_Next;
}
free(pCur->_Next);
pCur->_Next = NULL;
}
//查找有效节点个数
Node* SListFind(SList* s,SLTDatatype data)
{
assert(s);
assert(s->_Head != NULL);
PNode pCur = s->_Head;
int count = 0;
for (pCur; pCur != NULL; pCur = pCur->_Next)
{
if (pCur->_data == data)
{
return count+1;
}
count++;
}
return 0;
}
//查找节点的位置
Node* SListFindPos(SList* s, SLTDatatype data)
{
assert(s);
assert(s->_Head != NULL);
PNode pCur = s->_Head;
if (data < 1)
{
return s->_Head;
}
for (int i = 0; i < data-1;++i)
{
pCur = pCur->_Next;
}
return pCur;
}
//在pos后面的位置插入
void SListInsertAfter(PNode pos,SLTDatatype data)
{
PNode node = BuySListNode(data);
node->_Next = pos->_Next;
pos->_Next = node;
}
//删除pos后的节点
void SListEraseAfter(PNode pos)
{
if (pos->_Next == NULL)
{
return;
}
else
{
PNode node = pos->_Next->_Next;
free(pos->_Next);
pos->_Next = node;
}
}
//移除值为data的节点
void SListRemove(SList* s, SLTDatatype data)
{
assert(s);
if (s->_Head == NULL)
{
return;
}
if (s->_Head->_Next == NULL)
{
free(s->_Head);
s->_Head = NULL;
}
else
{
PNode pCur = s->_Head;
while (pCur->_Next != NULL)
{
PNode pPre = pCur;//pPre记录的是pCur的上一个
pCur = pCur->_Next;
if (pCur->_data == data)
{
pPre->_Next = pCur->_Next;
free(pCur);
pCur = pPre;
}
}
}
}
// 获取链表中有效节点的个数
size_t SListSize(SList* s)
{
if (s->_Head == NULL)
{
return 0;
}
else if (s->_Head->_Next == NULL)
{
return 1;
}
else
{
PNode pCur = s->_Head;
int count=0;
for (pCur; pCur!= NULL; pCur = pCur->_Next)
{
count++;
}
return count;
}
}
// 检测链表是否为空
int SListEmpty(SList* s)
{
if (s->_Head == NULL)
{
return 0;
}
else return 1;
}
// 将链表中有效节点清空
void SListClear(SList* s)
{
s->_Head = NULL;
}
//打印节点
void SListPrint(SList* s)
{
assert(s);
if (s->_Head == NULL)
{
printf("NULL\n");
}
else
{
PNode pCur = s->_Head;
while (pCur != NULL)
{
printf("%d--->", pCur->_data);
pCur = pCur->_Next;
}
printf("NULL\n");
}
}
void TestSList()
{
SList s;
SListInit(&s);
SListPushFront(&s,1);
SListPushFront(&s,2);
SListPushFront(&s,3);
SListPushFront(&s,4);
SListPushFront(&s,5);//头插测试
SListPrint(&s);
SListPopFront(&s);
SListPopFront(&s);
SListPopFront(&s);//头删测试
SListPrint(&s);
SListPushBack(&s, 0);
SListPushBack(&s, 1);
SListPushBack(&s, 2);//尾插测试
SListPrint(&s);
SListPopBack(&s);
SListPopBack(&s);
SListPopBack(&s);//尾删测试
SListPrint(&s);
SListPushFront(&s, 0);
SListPushFront(&s, 5);
SListPushFront(&s, 9);
SListPrint(&s);
printf("所查元素是第%d个\n",SListFind(&s,1));
//目前链表9--->5--->0--->2--->1--->NULL
//在第二个节点后面插入1
SListInsertAfter(SListFindPos(&s,2), 1);
SListPrint(&s);
//目前链表9--->5--->1--->0--->2--->1--->NULL
//在第5个节点后面插入1
SListInsertAfter(SListFindPos(&s,5), 1);
SListPrint(&s);
SListEraseAfter(SListFindPos(&s, 3));//把第三个节点后面的删掉
SListPrint(&s);
SListRemove(&s,1);//删除掉值为1的所有节点
SListPrint(&s);
SListSize(&s);
printf("有效节点的个数:%d \n", SListSize(&s));
SListEmpty(&s);
printf("%d\n", SListEmpty(&s));
SListClear(&s);
SListPrint(&s);
SListSize(&s);
printf("有效节点的个数:%d \n", SListSize(&s));
SListDestroy(&s);
}
int main()
{
TestSList();
system("pause");
return 0;
}