目录
(一)单链表的结构定义及初始化
(二)单链表的尾插,头插
(三)单链表的尾删,头删
(四)单链表的查找,删除,销毁
单链表是数据结构课程里的第二个数据结构。单链表在逻辑结构是连续的,在物理结构不一定连续。因为在单链表的每一个结点的内存是在堆区动态开辟的,由操作系统来决定是否连续开辟在相同的区域。
(一)单链表的结构定义及初始化
#define SLDataType int//单链表的结构定义
typedef struct SingleList
{SLDataType val;struct SingleList* next;
}SL;
单链表的每一个节点都有其数值域和指针域。数值域是当前结点所存储的数值,指针域是存储指向下一个结点的指针。这里我们定义一个宏,把SLDataType 替换成int,以后想换存储的数据类型就方便多了。我们再把单链表的数据类型struct SingleList重命名为SL。
//单链表的初始化
void InitSingleList(SL* phead)
{assert(phead);phead->val = 0;phead->next = NULL;
}
(二)单链表的尾插,头插
单链表的尾插是指在单链表的结尾插进去一个新结点。我们可以创建一个函数专门封装创建一个新结点的过程
//创建一个新结点
SL* BuyNewNode(SLDataType x)
{SL* NewNode = (SL*)malloc(sizeof(SL));if (NewNode == NULL){perror("malloc fail!\n");eixt(1); }//走到这说明新结点的内存创建成功NewNode->val = x;NewNode->next = NULL;return NewNode;
}
每次创建结点的时候必须要检查结点是否创建失败,而且要记得要释放空间。我们这里通过malloc申请了一片SL大小的空间。并将申请的空间解释为SL*类型,把SL里面的值赋值为x,下一个结点指向为NULL指针。
//单链表的尾插
void SingleListPushBack(SL** pphead, SLDataType x)
{//这里需要用二级指针,因为可能传进来的指针没有结点,尾插变成头插,需要对头结点的地址进行赋值。assert(pphead);SL* phead = *pphead;if (phead == NULL){//说明单链表没有一个结点,需要修改头结点的地址phead = BuyNewNode(x);}else{//需要遍历链表找到尾结点SL* pcur = phead;while (pcur){pcur = pcur->next;}//我们要让链表后面的顺序为 pcur -> NewNodepcur->next = BuyNewNode(x);}
}
//单链表的头插
void SingleListPushFront(SL** pphead, SLDataType x)
{ assert(pphead);//同样的头插就更需要传二级指针了SL* phead = *pphead;//NewNode -> phead;SL* NewNode = BuyNewNode(x);NewNode->next = phead;phead = NewNode;
}
(三)单链表的尾删,头删
同样的操作
//单链表的尾删
void SingleListPopBack(SL** pphead)
{assert(pphead && *phead);SL* phead = *pphead;//如果单链表只有一个结点if (phead-> next == NULL){free(phead);phead = NULL;}else{//需要遍历查找链表尾部SL* pcur = phead;SL* prev = NULL;while (pcur->next){prev = pcur;pcur = pcur->next;}// pcur pcur->nextprev->next = NULL;free(pcur->next);pcur->next = NULL;}
}
//单链表的头删
void SingleListPopFront(SL** pphead)
{ assert(pphead && *pphead);SL* phead = *pphead;// phead phead->next;SL* next = phead->next;free(phead);phead = next;
}
(四)单链表的查找,删除,销毁
//单链表的查找
SL* FindSingleList(SL* phead, SLDataType x)
{assert(phead);SL* pcur = phead;while (pcur){ if (pcur->val == x)return pcur;pcur = pcur->next;}return NULL;
}
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && pos);//pos就是头结点if (pos == *pphead){SLTPopFront(pphead);}else {SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//prev pos pos->nextprev->next = pos->next;free(pos);pos = NULL;}
}
//单链表的销毁
void SListDestroy(SLTNode** pphead)
{SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}