数据结构链表的(C语言)操作实现与详解

链表的概念与结构

概念:链表是一种物理存储结构上非连续、非顺序的储存结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

结构: 

 链式结构在逻辑上是连续的,但在物理上不一定连续,现实中的结点一般是从堆上申请出来的,从堆上申请空间,是按照一定策略来分配的,两次申请空间可能连续,也可能不连续。

 链表的分类

  1. 单向或双向
  2. 带头或不带头
  3. 循环或非循环 

实际中最常用无头单向非循环链表和带头双向循环链表 。 

( 本章只讲解无头单向非循环链表)

链表的实现  

        首先要想实现链表的增删查改,我们需要声明接口函数来实现。

声明接口函数

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLTDateType //重命名int

typedef struct SListNode //重命名结构体
{
    SLTDateType data; //链表存储的数据
    struct SListNode* next; //下一个节点的地址
}SLTNode;

//动态申请一个节点
SListNode* BuySListNode(SLTDateType)
//单链表打印
void SListPrint(SLTNode* phead);
//单链表尾插
void SListPushBack(SLTNode ** pphead, SLTDateType x);
//单链表头插
void SListPushFront(SLTNode** pphead, SLTDateType x);
//单链表尾删
void SListPopBack(SLTNode** pphead);
//单链表头删
void SListPopFront(SLTNode** pphead);
//单链表查找
SLTNode* SListFind(SLTNode* phead,SLTDateType X);
//单链表在pos位置前插入x
void SListInsert(SLTNode** pphead,SLTNode *pos ,SLTDateType x);
//单链表在pos位置后插入
void SListAfterInsert(SLTNode** pphead, SLTNode *pos, SLTDateType x);
//单链表的删除
void SListErase( SLTNode* pos ,SLTNode**pphead);
//单链表的销毁
void SListDestory(SLTNode** pphead);

接口函数的定义 

动态申请一个节点:

SLTNode* BuyListNode(SLTDateType x)
{
    SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//申请节点
    if(newnode == NULL)
    {
        printf("malloc fail\n");
        exit(-1);
    }
    newnode->Data = x;  //给节点初始化
    newnode->next = NULL;
    return newnode;
}

单链表打印:

void SListPrint(*phead)
{
    SLTNode* cur = phead;
    while(cur != NULL)
    {
        printf("%d->",cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}

单链表的尾插:

void SListPushBack(**pphead,SLTDateType x)
{
    SLTNode* newnode = BuyListNode(x);//申请一个节点
    if(*pphead == NULL)
    {
        *pphead = newnode;
    }
    else
    {
        SLTNode *tail = *phead;
        while(tail->next == NULL)
        {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}
    

单链表的头插:

void SListPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

单链表的尾删:

void SListPopBack(SLTNode**pphead)
{
	assert(*pphead != NULL);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	SLTNode* prev = NULL;
	SLTNode* tail = *pphead;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	tail = NULL;
	prev->next = NULL;
}

单链表的头删:

void SListPopFront(**pphead)
{    
    assert(*pphead != NULL);
    SLTNode* prev = NULL;
    prev = (*pphead)->next; //两个解引用所以用括号
    free(*pphead);
    *pphead = prev;
}

单链表查找:

STLnode* SListFind(SLTNode* phead, SLTDateType x)
{
    SLTNode* cur = phead;
    while(cur != NULL)
    {
        if(cur->data == x)
        {
            return cur;
        }
        else
        {
            cur = cur->next;
        }
    }
    return NULL;
}

单链表在pos位置前插入x:

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (pos == *pphead)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		SLTNode*posPrev = *pphead;
		while (posPrev->next != pos)
		{
			posPrev = posPrev->next;
		}
		posPrev->next = newnode;
		newnode->next = pos;
	}  
}

单链表在pos位置后插入x:

void SListAfterInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	SLTNode* cur = *pphead;
	SLTNode* newnode = BuyListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

单链表的删除:

​
void SListErase(SLTNode* pos, SLTNode** pphead)
{
    assert(pos != NULL);
	assert(*pphead != NULL);
	SLTNode* cur = *pphead;
	SLTNode* prev = NULL;
	if (*pphead == pos)
	{
		prev = pos->next;
		free(pos);
		pos = NULL;
		*pphead = prev;
	}
	else
	{
		while (cur != NULL)
		{
			if (cur == pos)
			{
				prev->next = cur->next;
				cur = cur->next;
				free(pos);
				pos = NULL;

			}
			else
			{
				prev = cur;
				cur = cur->next;
			}
		}
	}
	
}

​

单链表的销毁:

void SListDestory(SLTNode**pphead)
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur != NULL)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

感谢看到这里的老铁,如果文章有用请点个赞支持一下,感激不尽。

在下才疏学浅,一点浅薄之见,欢迎各位大佬指点。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

loveandsharef

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值