您的位置:首页 > 理论基础 > 数据结构算法

数据结构单链表的实现以及相关操作

2018-04-02 18:28 363 查看
首先在SListNode.h里面对我们的单链表结点结构体定义,以及相关操作函数进行声明
单链表部分主要相关操作包括单链表的数据的头插、尾插、头删、尾删、
SListNode.h:#pragma once
typedef int DataType;

typedef struct SListNode
{
struct SListNode* _next;
DataType _data;
}SListNode;//结点包括两部分,一个是指向结点类型的指针,一个是用来存放数据的data

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 SListInsest(SListNode** ppHead, SListNode* pos, DataType x);//在pos位置插入结点
void SListErase(SListNode** ppHead, SListNode* pos);//删除pos位置的结点接着在SListNode.c中对相关的操作函数进行定义,在main函数中进行测试#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"SListNode.h"

SListNode* BuySListNode(DataType x)//创建结点
{
SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));
if (tmp != NULL)
{
tmp->_data = x;
tmp->_next = NULL;
return tmp;
}
printf("节点创建失败!");
return tmp;
}

void SListPrint(SListNode* pHead)//打印单链表
{
if (pHead == NULL)
{
printf("该链表为空链表!\n");
}
else
{
while (pHead)
{
printf("%d->", pHead->_data);
pHead = pHead->_next;
}
printf("NULL\n");
}
}

void SListDestory(SListNode** ppHead)//删除整个单链表
{
SListNode* tmp;
if (*ppHead == NULL)
return;
else
{
while (*ppHead)
{
tmp = *ppHead;
*ppHead = (*ppHead)->_next;
free(tmp);
tmp = NULL;
}
}
}
void SListPushBack(SListNode** ppHead, DataType x)//从尾部插入数据
{
SListNode* newNode;
SListNode* tmp;
newNode = BuySListNode(x);
tmp = *ppHead;
if (NULL == *ppHead)
{
*ppHead = newNode;
(*ppHead)->_next = NULL;
}
else
{
while (tmp->_next)
{
tmp = tmp->_next;
}
tmp->_next = newNode;
newNode->_next = NULL;
}
}

void SListPopBack(SListNode** ppHead)//从尾部删除数据
{
//三种情况
//1.链表为空链表
//2.链表只有一个结点
//3.链表有多个节点
SListNode* tmp;
tmp = *ppHead;
if (*ppHead == NULL)
{
printf("该链表已经为空表,无需再删除元素!");
}
else if ((*ppHead)->_next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{

while ((tmp)->_next->_next)
{
tmp = tmp->_next;
}
free(tmp->_next);
tmp->_next = NULL;
}
}

void SListPushFront(SListNode** ppHead, DataType x)//从头部插入数据
{
SListNode* newNode;
newNode = BuySListNode(x);
if (*ppHead == NULL)//链表为空链表
{
*ppHead = newNode;
(*ppHead)->_next = NULL;
}
else
{
newNode->_next = *ppHead;
*ppHead = newNode;
}
}

void SListPopFront(SListNode** ppHead)//从头部删除数据
{
//三种情况
//1.链表为空链表
//2.链表只有一个结点
//3.链表有多个节点
SListNode* tmp;
tmp = *ppHead;
if (*ppHead == NULL)
{
printf("该链表已经为空表,无需再删除元素!");
}
else if ((*ppHead)->_next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
*ppHead = (*ppHead)->_next;
free(tmp);
tmp = NULL;
}

}
SListNode* SListFind(SListNode* pHead, DataType x)//找到链表中的某个元素
{
SListNode* tmp;
tmp = pHead;
while (tmp)
{
if (tmp->_data == x)
{
return tmp;
}
tmp = tmp->_next;
}
return tmp;
}

void SListInsest(SListNode** ppHead, SListNode* pos, DataType x)//在链表中pos位置插入 x
{
if (pos == NULL)
{
printf("该位置地址为空!无法插入!!\n");
}
else
{
SListNode* tmp;
SListNode* newNode;
newNode = BuySListNode(x);
tmp = *ppHead;
if (tmp == pos)
{
SListPushFront(ppHead, x);
return;
}
while (tmp)
{
if (tmp->_next == pos)
{
newNode->_next = tmp->_next;
tmp->_next = newNode;
return;
}
tmp = tmp->_next;
}
printf("该位置不在该顺序表中,插入失败!");
}
}

void SListErase(SListNode** ppHead, SListNode* pos)//删除链表中pos位置的元素
{
assert(pos);
SListNode* tmp;
SListNode* cur;
tmp = *ppHead;
while (tmp->_next == pos)
{
tmp = tmp->_next;
}
cur = tmp->_next;
tmp->_next = tmp->_next->_next;
free(cur);
cur = NULL;
}

int main()
{
SListNode* SList;
SList = BuySListNode(1);
SListPushBack(&SList,2);
SListPushBack(&SList, 3);
SListPushBack(&SList, 4);
SListPushBack(&SList, 5);
SListPrint(SList);
SListPopBack(&SList);
SListPushFront(&SList, 8);
SListPrint(SList);
SListInsest(&SList,SListFind(SList, 2), 9);
SListPopFront(&SList);
SListPrint(SList);
SListErase(&SList, SListFind(SList, 2));
SListPrint(SList);
SListDestory(&SList);
SListPrint(SList);
system("pause");
return 0;
}在对单链表进行摧毁删除时应该注意每一个结点都必须对它的内存进行释放,因为链表的这些结点每次插入新结点的时候都是在内存空间中用malloc进行申请,这些空间是不连续的。
跟顺序表的连续内存空间相比,单链表释放时要逐个释放,而不是只释放头结点然后将头指针置空,这块需要特别注意不能释放头结点后直接把指针置空,避免因为指针置空而找不到后续结点,导致内存泄漏 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 单链表