链表
链表:一种链式存储的线性表,用一组地址任一的存储单元存放线性表的数据元素,称存储单元为一各节点
单链表
1 . 结构
typedef int DataType;
typedef struct SListNode
{
DataType _data; // 当前节点中所保存的元素
struct SListNode* _pNext; // 指向下一个结点的指针
}Node, *PNode;
2 . 功能函数
包含链表的建立,初始化,头删,尾删,头插,尾插,任意位置的插入和删除,链表的输出,链表的判空等
// 初始化单链表
void SListInit(PNode* ppHead);
// 尾插
void SListPushBack(PNode* ppHead, DataType data);
// 尾删
void SListPopBack(PNode* ppHead);
// 头插
void SListPushFront(PNode* ppHead, DataType data);
// 头删
void SListPopFront(PNode* ppHead);
// 在链表中查找元素data,返回该结点在链表中的位置
PNode Find(PNode pHead, DataType data);
// data插入在pos之前
void SListInsert(PNode* ppHead, PNode pos, DataType data);
// 删除链表中pos位置的结点
void SListErase(PNode* ppHead, PNode pos);
// 获取链表中结点的个数
size_t Size(PNode pHead);
// 判断链表是否为空,若为空,返回true,否则返回false
size_t Empty(PNode pHead);
// 销毁单链表
void SListDestroy(PNode* pHead);
// 创建结点
PNode BuySListNode(DataType data);
// 打印单链表
void SListPrint(PNode pHead);
各部分功能的实现
- 初始化单链表
void SListInit(PNode* ppHead)
{
*ppHead = NULL;
}
- 尾插
// 尾插
void SListPushBack(PNode* ppHead, DataType data)
{
assert(ppHead);
PNode newP = BuySListNode(data);
PNode P = *ppHead;
if (*ppHead == NULL)
{
*ppHead = newP;
}
else
{
while (P->_pNext != NULL)
{
P = P->_pNext;
}
P->_pNext = newP;
}
}
- 尾删
// 尾删
void SListPopBack(PNode* ppHead)
{
assert(ppHead);
PNode Pre = NULL;
PNode Del = NULL;
if (*ppHead && (*ppHead) -> _pNext == NULL )
{
free((*ppHead));
*ppHead = NULL;
}
else if(*ppHead)
{
Del = *ppHead;
while (Del->_pNext != NULL)
{
Pre = Del;
Del = Del->_pNext;
}
Pre->_pNext = NULL;
free(Del);
}
}
- 头插
// 头插
void SListPushFront(PNode* ppHead, DataType data)
{
assert(ppHead);
PNode newP = BuySListNode(data);
newP->_pNext = *ppHead;
*ppHead = newP;
}
- 头删
// 头删
void SListPopFront(PNode* ppHead)
{
assert(ppHead);
PNode Del = NULL;
if((*ppHead) != NULL)
{
Del = *ppHead;
*ppHead = (*ppHead)->_pNext;
free(Del);
}
}
- 在链表中查找元素data,返回该结点在链表中的位置
// 在链表中查找元素data,返回该结点在链表中的位置
PNode Find(PNode pHead, DataType data)
{
while (pHead != NULL)
{
if (pHead->_data == data)
{
return pHead;
}
pHead = pHead->_pNext;
}
return NULL;
}
- data插入在pos之前
// data插入在pos之前
void SListInsert(PNode* ppHead, PNode pos, DataType data)
{
assert(ppHead);
assert(pos);
PNode Pnew = BuySListNode(data);
PNode per = NULL;
if (pos == *ppHead)
{
Pnew->_pNext = *ppHead;
*ppHead = Pnew;
}
else
{
per = *ppHead;
while (pos && per && per->_pNext != pos)
{
per = per->_pNext;
}
if (per->_pNext == pos)
{
Pnew->_pNext = pos;
per->_pNext = Pnew;
}
}
}
- 删除链表中pos位置的结点
// 删除链表中pos位置的结点
void SListErase(PNode* ppHead, PNode pos)
{
assert(ppHead);
PNode pre = *ppHead;
if(pos == NULL || *ppHead == NULL)
{
return 0;
}
else if (pos == *ppHead)
{
*ppHead = pos->_pNext;
free(pos);
}
else
{
while (pre && pre->_pNext != pos)
{
pre = pre->_pNext;
}
if (pre)
{
pre->_pNext = pos->_pNext;
free(pos);
}
}
}
- 获取链表中结点的个数
// 获取链表中结点的个数
size_t Size(PNode pHead)
{
size_t num = 0;
while (NULL != pHead)
{
num++;
pHead = pHead->_pNext;
}
return num;
}
- 判断链表是否为空,若为空,返回true,否则返回false
// 判断链表是否为空,若为空,返回true,否则返回false
size_t Empty(PNode pHead)
{
if (NULL == pHead)
{
return 1;
}
else return 0;
}
- 销毁单链表
// 销毁单链表
void SListDestroy(PNode* pHead)
{
assert(pHead);
if ((*pHead) != NULL)
{
SListDestroy(&((*pHead)->_pNext));
}
if((*pHead) != NULL)
{
free((*pHead));
}
}
- 创建结点
// 创建结点
PNode BuySListNode(DataType data)
{
PNode newP = NULL;
newP = (PNode)malloc(sizeof(Node));
if (newP == NULL)
{
printf("error\n");
return 0;
}
newP->_data = data;
newP->_pNext = NULL;
return newP;
}
- 打印单链表
// 打印单链表
void SListPrint(PNode pHead)
{
while (pHead != NULL)
{
printf("%d ", pHead->_data);
pHead=pHead->_pNext;
}
printf("\n");
}
代码
代码实现(Visual studio 2017)
- test.c 文件
//主函数
int main()
{
//尾插测试
PushBack_test();
//尾删测试
PopBack_test();
//头插测试
PushFront_test();
//头删测试
PophFront_test();
//data插入在pos之前测试
SListInsert_test();
// 删除链表中pos位置的结点
SListErase_test();
// 链表中结点个数测试
Size_test();
// 销毁单链表测试
SListDestroy_test();
system("pause");
return 0;
}
- SListNode.h 文件
#pragma once
#ifndef _SLISTNODE_H_
#define _SLISTNODE_H_
typedef int DataType;
typedef struct SListNode
{
DataType _data;
struct SListNode* _pNext; // 指向下一个结点的指针
}Node, *PNode;
// 初始化单链表
void SListInit(PNode* ppHead);
// 尾插
void SListPushBack(PNode* ppHead, DataType data);
// 尾删
void SListPopBack(PNode* ppHead);
// 头插
void SListPushFront(PNode* ppHead, DataType data);
// 头删
void SListPopFront(PNode* ppHead);
// 在链表中查找元素data,返回该结点在链表中的位置
PNode Find(PNode pHead, DataType data);
// data插入在pos之前
void SListInsert(PNode* ppHead, PNode pos, DataType data);
// 删除链表中pos位置的结点
void SListErase(PNode* ppHead, PNode pos);
// 获取链表中结点的个数
size_t Size(PNode pHead);
// 判断链表是否为空,若为空,返回true,否则返回false
size_t Empty(PNode pHead);
// 销毁单链表
void SListDestroy(PNode* pHead);
// 创建结点
PNode BuySListNode(DataType data);
// 打印单链表
void SListPrint(PNode pHead);
#endif
- SListNode.c 文件
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include "SListNode.h"
// 初始化单链表
void SListInit(PNode* ppHead)
{
*ppHead = NULL;
}
// 尾插
void SListPushBack(PNode* ppHead, DataType data)
{
assert(ppHead);
PNode newP = BuySListNode(data);
PNode P = *ppHead;
if (*ppHead == NULL)
{
*ppHead = newP;
}
else
{
while (P->_pNext != NULL)
{
P = P->_pNext;
}
P->_pNext = newP;
}
}
// 尾删
void SListPopBack(PNode* ppHead)
{
assert(ppHead);
PNode Pre = NULL;
PNode Del = NULL;
if (*ppHead && (*ppHead) -> _pNext == NULL )
{
free((*ppHead));
*ppHead = NULL;
}
else if(*ppHead)
{
Del = *ppHead;
while (Del->_pNext != NULL)
{
Pre = Del;
Del = Del->_pNext;
}
Pre->_pNext = NULL;
free(Del);
}
}
// 头插
void SListPushFront(PNode* ppHead, DataType data)
{
assert(ppHead);
PNode newP = BuySListNode(data);
newP->_pNext = *ppHead;
*ppHead = newP;
}
// 头删
void SListPopFront(PNode* ppHead)
{
assert(ppHead);
PNode Del = NULL;
if((*ppHead) != NULL)
{
Del = *ppHead;
*ppHead = (*ppHead)->_pNext;
free(Del);
}
}
// 在链表中查找元素data,返回该结点在链表中的位置
PNode Find(PNode pHead, DataType data)
{
while (pHead != NULL)
{
if (pHead->_data == data)
{
return pHead;
}
pHead = pHead->_pNext;
}
return NULL;
}
// data插入在pos之前
void SListInsert(PNode* ppHead, PNode pos, DataType data)
{
assert(ppHead);
assert(pos);
PNode Pnew = BuySListNode(data);
PNode per = NULL;
if (pos == *ppHead)
{
Pnew->_pNext = *ppHead;
*ppHead = Pnew;
}
else
{
per = *ppHead;
while (pos && per && per->_pNext != pos)
{
per = per->_pNext;
}
if (per->_pNext == pos)
{
Pnew->_pNext = pos;
per->_pNext = Pnew;
}
}
}
// 删除链表中pos位置的结点
void SListErase(PNode* ppHead, PNode pos)
{
assert(ppHead);
PNode pre = *ppHead;
if(pos == NULL || *ppHead == NULL)
{
return 0;
}
else if (pos == *ppHead)
{
*ppHead = pos->_pNext;
free(pos);
}
else
{
while (pre && pre->_pNext != pos)
{
pre = pre->_pNext;
}
if (pre)
{
pre->_pNext = pos->_pNext;
free(pos);
}
}
}
// 获取链表中结点的个数
size_t Size(PNode pHead)
{
size_t num = 0;
while (NULL != pHead)
{
num++;
pHead = pHead->_pNext;
}
return num;
}
// 判断链表是否为空,若为空,返回true,否则返回false
size_t Empty(PNode pHead)
{
if (NULL == pHead)
{
return 1;
}
else return 0;
}
// 销毁单链表
void SListDestroy(PNode* pHead)
{
assert(pHead);
if ((*pHead) != NULL)
{
SListDestroy(&((*pHead)->_pNext));
}
if((*pHead) != NULL)
{
free((*pHead));
}
}
// 创建结点
PNode BuySListNode(DataType data)
{
PNode newP = NULL;
newP = (PNode)malloc(sizeof(Node));
if (newP == NULL)
{
printf("error\n");
return 0;
}
newP->_data = data;
newP->_pNext = NULL;
return newP;
}
// 打印单链表
void SListPrint(PNode pHead)
{
while (pHead != NULL)
{
printf("%d ", pHead->_data);
pHead=pHead->_pNext;
}
printf("\n");
}
//尾插测试
void PushBack_test()
{
PNode pHead;
SListInit(&pHead);
printf("尾插测试\n");
SListPushBack(&pHead, 0);
SListPrint(pHead);
SListPushBack(&pHead, 1);
SListPrint(pHead);
SListPushBack(&pHead, 2);
SListPrint(pHead);
SListPushBack(&pHead, 3);
SListPrint(pHead);
SListPushBack(&pHead, 4);
SListPrint(pHead);
}
//尾删测试
void PopBack_test()
{
PNode pHead;
SListInit(&pHead);
printf("尾删测试\n");
SListPushBack(&pHead, 0);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
SListPopBack(&pHead);
SListPrint(pHead);
}
//头插测试
void PushFront_test()
{
PNode pHead;
SListInit(&pHead);
printf("头插测试\n");
SListPushFront(&pHead, 1);
SListPrint(pHead);
SListPushFront(&pHead, 2);
SListPrint(pHead);
SListPushFront(&pHead, 3);
SListPrint(pHead);
SListPushFront(&pHead, 4);
SListPrint(pHead);
SListPushFront(&pHead, 5);
SListPrint(pHead);
SListPushFront(&pHead, 6);
SListPrint(pHead);
}
//头删测试
void PophFront_test()
{
PNode pHead;
SListInit(&pHead);
printf("头删测试\n");
SListPushFront(&pHead, 1);
SListPushFront(&pHead, 2);
SListPushFront(&pHead, 3);
SListPushFront(&pHead, 4);
SListPushFront(&pHead, 5);
SListPushFront(&pHead, 6);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
SListPopFront(&pHead);
SListPrint(pHead);
}
//data插入在pos之前测试
void SListInsert_test()
{
PNode pHead;
SListInit(&pHead);
printf("插入测试\n");
SListPushBack(&pHead, 0);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPrint(pHead);
SListInsert(&pHead, Find(pHead,0), 9);
SListPrint(pHead);
SListInsert(&pHead, Find(pHead, 2), 9);
SListPrint(pHead);
SListInsert(&pHead, Find(pHead, 4), 9);
SListPrint(pHead);
}
// 删除链表中pos位置的结点
void SListErase_test()
{
PNode pHead;
SListInit(&pHead);
printf("删除测试\n");
SListPushBack(&pHead, 0);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPrint(pHead);
SListErase(&pHead, Find(pHead, 0));
SListPrint(pHead);
SListErase(&pHead, Find(pHead, 2));
SListPrint(pHead);
SListErase(&pHead, Find(pHead, 4));
SListPrint(pHead);
SListErase(&pHead, Find(pHead, 1));
SListPrint(pHead);
SListErase(&pHead, Find(pHead, 3));
SListPrint(pHead);
}
// 链表中结点个数测试
void Size_test()
{
int num = 0;
PNode pHead;
SListInit(&pHead);
printf("个数测试\n");
SListPushBack(&pHead, 0);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPrint(pHead);
num = Size(pHead);
printf("节点个数为:%d \n", num);
}
// 销毁单链表测试
void SListDestroy_test()
{
PNode pHead;
SListInit(&pHead);
printf("销毁测试\n");
SListPushBack(&pHead, 0);
SListPushBack(&pHead, 1);
SListPushBack(&pHead, 2);
SListPushBack(&pHead, 3);
SListPushBack(&pHead, 4);
SListPrint(pHead);
SListDestroy(&pHead);
}