作者:小琛
欢迎转载,请标明出处
单链表的概念
概念:链表是一种物理存储结构上非连续、非顺序,逻辑上连续的结构是通过链表中的指针链 接次序实现的。如下图:
也就是说,我们的链表逻辑是借助结构体实现的,结构体允许成员包括自调用指针,因此我们定义的结构体内容包括两个:date即数据,自调用指针
单链表的实现
单链表的实现方式很多,这里鉴于后续的面试和oj题目类型,实现不带头节点、二级指针写法的单链表
手写单链表的主要目的还是了解清楚其逻辑,因此本博文实现了几个基本的功能
Plist.h
#ifndef _LIST_H__
#define _LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DateType;
typedef struct PlistNode
{
DateType _date;
struct PlistNode* _next;
}PlistNode;
PlistNode* GetNode(DateType x);
void PushBack(PlistNode** pplist, DateType x);
void PopBack(PlistNode** pplist);
void PushFront(PlistNode** pplist, DateType x);
void PopFront(PlistNode** pplist);
PlistNode* ListFind(PlistNode* plist, DateType x);
void ListInsertAfter(PlistNode** pos, DateType x);
void SListEraseAfter(PlistNode** pos);
void Print(PlistNode* plist);
#endif
Plist.c
#include "List.h"
/*
函数功能:得到一个新的节点,并将要插入得值赋给该节点
入口参数:要插入得值
返回值:新节点的指针
*/
PlistNode* GetNode(DateType x)
{
PlistNode* NewNode = (PlistNode*)malloc(sizeof(PlistNode));
NewNode->_date = x;
NewNode->_next = NULL;
return NewNode;
}
/*
函数功能:尾插法
入口参数:某链表的头的地址,要插入的值
返回值:无
*/
void PushBack(PlistNode** pplist, DateType x)
{
PlistNode* NewNode = GetNode(x);
if (*pplist == NULL)
{
*pplist = NewNode;
}
else
{
PlistNode* tail = *pplist;
while (tail->_next != NULL)
{
tail = tail->_next;
}
tail->_next = NewNode;
}
}
/*
函数功能:尾删法
入口参数:某链表的头的地址
返回值:无
*/
void PopBack(PlistNode** pplist)
{
//两情况:只有一个或零个数据、多个数据
if (*pplist == NULL || (*pplist)->_next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
PlistNode* cur = *pplist;
PlistNode* prv = NULL;
while (cur->_next)
{
prv = cur;
cur = cur->_next;
}
free(cur);
cur = NULL;
prv->_next = NULL;
}
}
/*
函数功能:头插法
入口参数:某链表的头的地址,要插入的值
返回值:无
*/
void PushFront(PlistNode** pplist, DateType x)
{
PlistNode* NewNode = GetNode(x);
if (*pplist == NULL)
{
*pplist = NewNode;
}
else
{
NewNode->_next = *pplist;
*pplist = NewNode;
}
}
/*
函数功能:头插法
入口参数:某链表的头的地址
返回值:无
*/
void PopFront(PlistNode** pplist)
{
//无、一个、多个
if (*pplist == NULL)
{
return;
}
else if ((*pplist)->_next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
PlistNode* cur = (*pplist)->_next;
free(*pplist);
*pplist = cur;
}
}
/*
函数功能:查找函数
入口参数:某链表的头的地址,要查找的值
返回值:无
*/
PlistNode* ListFind(PlistNode* plist, DateType x)
{
assert(plist);
PlistNode* cur = plist;
while (cur != NULL)
{
if (x == cur->_date)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
/*
函数功能:在一个链表的pos位后插入
入口参数:一个链表的某一个节点,要插入的值
返回值:无
*/
void ListInsertAfter(PlistNode** pos, DateType x)
{
PlistNode* cur = GetNode(x);
PlistNode* tmp = NULL;
tmp = (*pos)->_next;
(*pos)->_next = cur;
cur->_next = tmp;
}
/*
函数功能:删除某个链表pos后的一个节点
入口参数:一个链表的某个节点
返回值:无
*/
void SListEraseAfter(PlistNode** pos)
{
PlistNode* tmp = NULL;
PlistNode* cur = NULL;
tmp = (*pos)->_next;
cur = tmp->_next;
(*pos)->_next = cur;
free(tmp);
tmp = NULL;
}/*
函数功能:打印函数
入口参数:某链表的头的地址
返回值:无
*/
void Print(PlistNode* plist)
{
PlistNode* cur = plist;
while (cur != NULL)
{
printf("%d\n", cur->_date);
cur = cur->_next;
}
printf("\n");
}
text.c
#include "List.h"
void text1()
{
PlistNode* head = NULL;
PlistNode* cur = NULL;
PushBack(&head, 1);
PushBack(&head, 2);
PushBack(&head, 3);
PushBack(&head, 4);
PushBack(&head, 5);
Print(head);
PopBack(&head);
Print(head);
PushFront(&head, 0);
Print(head);
cur=ListFind(head, 4);
Print(cur);
ListInsertAfter(&cur, 100);
Print(head);
SListEraseAfter(&cur);
Print(head);
}
void text2()
{
PlistNode* head1 = NULL;
PushFront(&head1, 0);
PushFront(&head1, 1);
PushFront(&head1, 2);
Print(head1);
PopFront(&head1);
Print(head1);
PopFront(&head1);
Print(head1);
PopFront(&head1);
Print(head1);
}
int main()
{
text1();
//text2();
return 0;
}