单链表是一种链式存取的数据结构,用申请的地址存放每个节点,这些地址可能是连续,也可能是不连续的。每个结点的构成:元素(数据元素的映象,data) + 指针(指示后继元素存储位置,next)。通过指针将线性表的数据一个个串联起来,要想访问一个数据,就要知道前一个指针,想知道前一个就要知道前前一个,依次向前找。所以,一般访问是从头指针开始向后查找目标,方向是单向的。
头指针一般是固定的,而尾指针随着链表的增加或删除可能会改变,但是尾指针的后继节点一定是指向空,即NULL的。
下面便是单链表的增、删、查、改操作。
SingleLinkedList.h(头文件)
#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#include<Windows.h>
typedef int DataType;
typedef struct SListNode
{
struct SListNode* _next;
DataType _data;
}SListNode;
SListNode* pStructInit();//结构体指针初始
SListNode* BuySListNode(DataType x);//创建节点
void SListPrint(SListNode* pHead);//打印
void SListDestory(SListNode** ppHead);//销毁
void SListPushBack(SListNode** ppHead, DataType x);//尾插
void SListPopBack(SListNode** ppHead);//尾删
void SListPushFront(SListNode** ppHead, DataType x);//头插
void SListPopFront(SListNode** ppHead);//头删
SListNode* SListFind(SListNode* pHead, DataType x);//查找
void SListInsert(SListNode** ppHead, SListNode* pos, DataType x);//pos前插入
void SListErase(SListNode** ppHead, SListNode* pos);//pos位置删除
void SListAt(SListNode** ppHead, SListNode *pos, DataType x);//替换
SingleLinkedList.c(功能函数的实现)
#include"SingleLinkedList.h"
SListNode* pStructInit()//结构体指针初始
{
SListNode* pStruct = (SListNode*)malloc(sizeof(SListNode));
if (pStruct == NULL)
{
perror("Initialize fail");
exit(1);
}
pStruct->_next = NULL;
return pStruct;
}
SListNode* BuySListNode(DataType x)//创建节点
{
SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
if (tmp == NULL)
{
perror("Malloc fail");
exit(1);
}
tmp->_data = x;
tmp->_next = NULL;
return tmp;
}
void SListPrint(SListNode* pHead)//打印单链表
{
assert(pHead);
SListNode* pnode = pHead->_next;
while (pnode)
{
printf("%d ", pnode->_data);
pnode = pnode->_next;
}
printf("\n");
}
void SListDestory(SListNode** ppHead)//销毁
{
SListNode* tmp = NULL;
while (*ppHead)
{
tmp = (*ppHead)->_next;
free(*ppHead);
(*ppHead) = tmp;
}
}
void SListPushBack(SListNode** ppHead, DataType x)//尾插
{
assert(ppHead);
SListNode* tmp = *ppHead;
if (ppHead == NULL)
{
*ppHead = BuySListNode(x);
return;
}
while (tmp->_next)
{
tmp = tmp->_next;
}
tmp->_next = BuySListNode(x);
}
void SListPopBack(SListNode** ppHead)//尾删
{
assert(ppHead);
SListNode* tmp = *ppHead;
if ((tmp->_next)==NULL)//无节点
{
return;
}
else//有节点
{
while (tmp->_next->_next)
{
tmp = tmp->_next;
}
//将最后一个元素销毁置空
free(tmp->_next);
tmp->_next = NULL;
}
}
void SListPushFront(SListNode** ppHead, DataType x)//头插
{
assert(ppHead);
if ((*ppHead) == NULL)
{
*ppHead = BuySListNode(x);
(*ppHead)->_next = NULL;
}
else
{
SListNode *tmp = BuySListNode(x);
tmp->_next = (*ppHead)->_next;
(*ppHead)->_next = tmp;
}
}
void SListPopFront(SListNode** ppHead)//头删
{
assert(ppHead);
if ((*ppHead)->_next == NULL)
{
return;
}
else
{
SListNode *tmp = (*ppHead)->_next;
(*ppHead)->_next = tmp->_next;
free(tmp);
tmp = NULL;
}
}
SListNode* SListFind(SListNode* pHead, DataType x)//查找
{
SListNode* tmp = pHead;
while (tmp)
{
if (tmp->_data == x)
return tmp;
else
tmp = tmp->_next;
}
return NULL;
}
void SListInsert(SListNode** ppHead, SListNode* pos, DataType x)//pos前插入
{
assert(ppHead && pos);
SListNode *p = (*ppHead);
SListNode *q = BuySListNode(x);
while (p->_next != pos)
{
p = p->_next;
}
p->_next = q;
q->_next = pos;
}
void SListErase(SListNode** ppHead, SListNode* pos)//pos位置删除
{
assert(ppHead && pos);
SListNode* tmp = *ppHead;
while (tmp->_next != pos)
{
tmp = tmp->_next;
}
tmp->_next = pos->_next;
free(pos);
pos = NULL;
}
void SListAt(SListNode** ppHead, SListNode *pos, DataType x)//替换
{
assert(ppHead && pos);
SListNode *tmp = *ppHead;
while (tmp->_next != pos)
{
tmp = tmp->_next;
}
tmp->_next->_data = x;
}
Test.c(测试)
#include"SingleLinkedList.h"
void TestPushBack(SListNode *list)//尾插
{
SListPushBack(&list, 1);
SListPrint(list);
SListPushBack(&list, 2);
SListPrint(list);
SListPushBack(&list, 3);
SListPrint(list);
SListDestory(&list);
}
void TestPopBack(SListNode *list)//尾删
{
SListNode*tmp = list;
//先插入3个数字
SListPushBack(&list, 1);
SListPushBack(&list, 2);
SListPushBack(&list, 3);
SListPrint(list);
list = tmp;
//开始尾删
SListPopBack(&tmp);
SListPrint(tmp);
SListPopBack(&tmp);
SListPrint(tmp);
SListPopBack(&tmp);
SListPrint(tmp);
SListDestory(&list);
}
void TestPushFront(SListNode *list)//头插
{
SListPushFront(&list, 1);
SListPrint(list);
SListPushFront(&list, 2);
SListPrint(list);
SListPushFront(&list, 3);
SListPrint(list);
SListDestory(&list);
}
void TestPopFront(SListNode *list)//头删
{
SListPushFront(&list, 1);
SListPushFront(&list, 2);
SListPushFront(&list, 3);
SListPrint(list);
SListPopFront(&list);
SListPrint(list);//删掉3剩下2和1
SListPopFront(&list);
SListPrint(list);//剩下1
SListPopFront(&list);
SListPrint(list);//空
SListPopFront(&list);
SListPrint(list);//空
SListDestory(&list);
}
void TestInsert(SListNode *list)//pos前插入
{
SListNode*pos = NULL;
//尾插
SListPushBack(&list, 7);
SListPushBack(&list, 8);
SListPushBack(&list, 9);
//头插
SListPushFront(&list, 3);
SListPushFront(&list, 2);
SListPushFront(&list, 1);
SListPrint(list);
pos = SListFind(list,7);
SListInsert(&list,pos, 6);
SListPrint(list);
pos = SListFind(list, 6);
SListInsert(&list, pos, 5);
SListPrint(list);
pos = SListFind(list, 5);
SListInsert(&list, pos, 4);
SListPrint(list);
/*pos = SListFind(list, 20);//因为链表没有20,pos为空指针,在SListInsert函数的断言会报错
SListInsert(&list, pos, 10);
SListPrint(list);*/
SListDestory(&list);
}
void TestErase(SListNode *list)//pos位置删除
{
SListNode*pos = NULL;
//尾插
SListPushBack(&list, 7);
SListPushBack(&list, 8);
SListPushBack(&list, 9);
//头插
SListPushFront(&list, 3);
SListPushFront(&list, 2);
SListPushFront(&list, 1);
SListPrint(list);
pos = SListFind(list,1);
SListErase(&list, pos);
SListPrint(list);
pos = SListFind(list, 2);
SListErase(&list, pos);
SListPrint(list);
pos = SListFind(list, 3);
SListErase(&list, pos);
SListPrint(list);
pos = SListFind(list, 7);
SListErase(&list, pos);
SListPrint(list);
pos = SListFind(list, 8);
SListErase(&list, pos);
SListPrint(list);
pos = SListFind(list, 9);
SListErase(&list, pos);
SListPrint(list);
SListDestory(&list);
}
void TestFind(SListNode *list)//查找
{
SListPushBack(&list, 1);
SListPushBack(&list, 2);
SListPushBack(&list, 3);
//数据存在,打印该数据;查找不存在数据会发生异常
printf("%d\n", SListFind(list, 3)->_data);
printf("%d\n", SListFind(list, 2)->_data);
printf("%d\n", SListFind(list, 1)->_data);
//printf("%d\n", SListFind(list, 0)->_data);//链表内没有数据data存放0,因此返回NULL,而用空指针访问data数据会异常
SListDestory(&list);
}
void TestAt(SListNode *list)//替换
{
SListNode*pos = NULL;
//头插
SListPushFront(&list, 3);
SListPushFront(&list, 2);
SListPushFront(&list, 0);
//尾插
SListPushBack(&list, 4);
SListPushBack(&list, 8);
SListPushBack(&list, 9);
SListPrint(list);
pos = SListFind(list, 0);
SListAt(&list, pos, 1);
SListPrint(list);
pos = SListFind(list, 8);
SListAt(&list, pos, 5);
SListPrint(list);
pos = SListFind(list, 9);
SListAt(&list, pos, 6);
SListPrint(list);
SListDestory(&list);
}
int main()//想要测试哪个,则放开前面的双斜线
{
SListNode *list = pStructInit();
//TestPushBack(list);//尾插
//TestPopBack(list);//尾删
//TestPushFront(list);//头插
//TestPopFront(list);//头删
//TestInsert(list);//pos前插入
//TestErase(list);//pos位置删除
//TestFind(list);//查找
//TestAt(list);//替换
system("pause");
return 0;
}