目录
1)单链表结构体的创建
首先头文件的定义,对于单链表的结构体进行初始化,以及对用到的链表函数进行声明。
#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLNode;
void SListprint(SLNode* phead);//链表打印函数
void SListPushBack(SLNode** pphead, SLTDataType x);//链表尾插入函数
void SListPushFront(SLNode** pphead, SLTDataType x);//链表头插入函数
void SListPopback(SLNode** pphead );//链表尾删
void SListPopFront(SLNode** pphead);//链表头删
void SListInser(SLNode** pphead, SLNode* pos, SLTDataType x);//链表节点插入函数
SLNode* SListFind(SLNode* phead, SLTDataType x);
SLNode* BuyListNode(SLTDataType x);
2)单链表的尾插、头插、尾删、头删以及链表的输出
#include "reSL.h"
//链表输出函数
//******************************************
void SListprint(SLNode* phead)
{
SLNode* cur = phead;//定义一个基地指针,进行链表的输出
while (cur != NULL)//基地指针不为空,就一直循环
{
printf("%d\n", cur->data);//输出本次找到节点的数据data
cur = cur->next;//下一次输出作准备
}
}
//******************************************
//链表尾插
//******************************************
void SListPushBack(SLNode** pphead, SLTDataType x)
{
//SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
//newnode->data = x;
//newnode->next = NULL;
//上面三条,是链表节点还没封装
SLNode* newnode = BuyListNode(x);//把新节点,封装成为一个子函数,调用即可
if (*pphead == NULL)
{
*pphead = newnode; //判断链表是否为空,空的话,让链表头指针指向新节点
}
else//链表不为空,我们需要找到尾节点
{
// 找到尾节点
SLNode* tail = *pphead;//定义一个基地指针,来寻找尾节点
while (tail->next != NULL)//寻找尾节点
{
tail = tail->next;
}
tail->next = newnode;//找到尾节点了,让尾节点的next指向新的节点newnode
}
}
//******************************************
//链表节点创建函数
//******************************************
SLNode* BuyListNode(SLTDataType x)
{
// 1M = 1024KB = 1024 * 1024 Byte
SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
//******************************************
//链表头插
//******************************************
void SListPushFront(SLNode** pphead, SLTDataType x)
{
SLNode* newnode = BuyListNode(x);//创建一个新的链表节点newnode
newnode->next= *pphead;//让新节点的next,指向链表开始的位置,也就是头指针指向的
*pphead = newnode;//让链表头指针指向新的节点
}
//******************************************
//链表尾删
//******************************************
void SListPopback(SLNode** pphead )
{
if (*pphead == NULL)//判断头节点是否为空
{
return;//空的话退出,没有东西可以删
}
if(( *pphead)->next == NULL)//判断是不是只有一个节点的情况
{
free(*pphead);//是的话,释放这个空间
*pphead = NULL;//让链表头指针变为空指针
}
else//两个节点以上情况
{
SLNode* tail = *pphead;//定义一个基地指针,让它开始等于头指针
while (tail->next->next)//判断第二个节点的next是不是指向了NULL
{
tail = tail->next;//如果第二个节点next没有指向NULL,则进行移动基地指针
//让它到第二个节点的位置去
}
free(tail->next);//上面的循环结束,说明基地指针tail现在在倒数第二个节点的位置
//现在可以删掉最后一个节点,释放内存空间
tail->next = NULL;//这个很关键,需要把倒数第二个节点的nxet指向NULL,因为链表都是以NULL结尾
}
}
//******************************************
//链表头删
//******************************************
void SListPopFront(SLNode** pphead)
{
if (*pphead == NULL)
{
return;
}
SLNode* next = (*pphead)->next;//设置链表第二个节点
free(*pphead);//释放链表第一个节点
*pphead = next;//让链表头指针指向第二个节点,作为新链表的头结点
}
//******************************************
2.1)进行测试单链表基础函数是否功能正常
void test01()
{
SLNode* PList = NULL;
SListPushBack(&PList,2);//链表尾插入函数
SListPushBack(&PList,1);//链表尾插入函数
SListPushBack(&PList,2);//链表尾插入函数
SListPushFront(&PList,5);//链表尾插入函数
SListprint(PList);
//输出为5212
SListPopback(&PList);//链表尾删
SListPopFront(&PList);//链表头删
SListprint(PList);
//输出为21
SLNode* pos = SListFind(PList,1);
SListInser(&PList,pos,100);
SListprint(PList);
}
2.2)测试结果
链表可以正常进行头插和尾插
3)单链表的查找函数
//链表查找数据函数
SLNode* SListFind(SLNode* phead, SLTDataType x)
{
if (phead == NULL)//为了防止链表为空
{
return;
}
SLNode* cur = phead;//定义一个基地指针
while (cur)
{
if (cur->data == x)//判断查找的数据是否相等
{
return cur;//相等的话,返回指针
}
else
{
cur = cur->next;//不相等的话,进行下一个节点查找
}
}
return NULL;//如果都没找到的话,返回空
}
//******************************************
3.1)测试验证函数功能是否正常
void test02()//验证查找函数 SListFind
{
SLNode* PList = NULL;
SListPushBack(&PList, 2);//链表尾插入函数
SListPushBack(&PList, 5);//链表尾插入函数
SListPushBack(&PList, 8);//链表尾插入函数
SListPushBack(&PList, 3);//链表尾插入函数
SListPushBack(&PList, 4);//链表尾插入函数
SListPushBack(&PList, 7);//链表尾插入函数
//2\5\8\3\4\7
SLNode* pos1 = SListFind(PList, 8);
if (pos1)
{
pos1->data = 100;//找到8,并且修改为100
}
SListprint(PList);
//2\5\100\3\4\7
}
4)链表中任意位置数据的插入(前插)
//在POS位置前插入一个节点
void SListInser(SLNode** pphead, SLNode* pos, SLTDataType x)
{
SLNode* newnode = BuyListNode(x);//创建一个新的链表节点newnode
if (*pphead == NULL)
{
return;
}
if (*pphead == pos)//如果是头节点,进行头插入
{
newnode->next = *pphead;
*pphead = newnode;
}
else//两个以上节点
{
SLNode* prepos = *pphead;//定义一个寻找pos前一个位置的节点
while (prepos->next != pos)//找pos的位置
{
prepos = prepos->next;//进行移位
}
prepos->next = newnode;//找pos前一个位置的节点,进行插入
newnode->next = pos;
}
}
//******************************************
4.1)验证测试功能是否正常
void test03()
{
SLNode* PList = NULL;
SListPushBack(&PList, 5);//链表尾插入函数
SListPushBack(&PList, 2);//链表尾插入函数
SListPushBack(&PList, 5);//链表尾插入函数
SListPushBack(&PList, 2);//链表尾插入函数
SListPushBack(&PList, 5);//链表尾插入函数
SListPushBack(&PList, 5);//链表尾插入函数
SLNode* pos = SListFind(PList, 5);
int i = 1;
while (pos !=NULL)
{
printf("第%d个pos节点:%p->%d\n",i++,pos,pos->data);
SListInser(&PList,pos,520);//找到的话,在前面插入100
pos = SListFind(pos->next, 5);//在第一次的基础上,进行下一次查找
SListprint(PList);
}
}