单向不带头链表 c语言接口实现(头插、头删、尾插、尾删、指定位置删插等接口)解释

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

链表分类: 单向、双向
                  带头、不带头
                  循环、非循环

常用链表类型:

1.无头单向非循环链表

typedef struct Node{

    int value;   //保存链表每个节点的数值
    
    struct Node* next;   //结构体指针,指向链表中数值的地址
}   Node;

  2.带头双向循环链表

typedef struct Node{

    int value;   //保存链表每个节点的数值
    
    struct Node* next;   
    struct Node* prev;   //
}   Node;

本文只介绍单向链表

1.链表结构功能

SList.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#pragma once

//链表的节点
typedef struct Node
{
	//结构体中的数值
	int value;
	//数组指针,存放每个数的地址
	struct Node* next;     //申请结构体指针数组,指向链表中数值的地址
} Node;


Node* first;

//首个元素申请内存,并存入作为第一个元素
Node* BuyNode(int v);

//链表初始化
void SListInit(Node** pFirst);

//链表销毁
void SListDestory(Node* first);

//头插
void SListPushFront(Node** pFirst, int v);

//头删
void SListPopFront(Node** pFirst);

//尾插
void SListPushBack(Node** pFirst, int v);

//尾删
void SListPopBack(Node** pFirst);

//指定位置插
void SListInsert(Node* pos, int v);

//指定位置删
void SListErase(Node* pos);

//指定值查找
Node* SListFind(Node* first, int v);

//删除第一个遇到的指定值v
void SListRemove(Node** pFirst, int v);

//删除遇到的所有指定值v
void SListRemoveAll(Node** pFirst, int v);

//统计链表中的元素个数
int GetListLength(Node* first);

//打印链表中所有数字元素
void SListPrint(Node* first);

2.接口实现函数c实现

SList.c

#include "SList.h"


//首个元素申请内存,并存入作为第一个元素
Node* BuyNode(int v)
{
	//v = date_input();
	Node* start = (Node*)malloc(sizeof(Node));
	if (start == NULL)
	{
		perror("BuyNode::malloc");
		return NULL;
	}
	start->value = v;
	start->next = NULL;

	return start;
}



//链表初始化
void SListInit(Node** pFirst)
{
	*pFirst = NULL;
}

//链表销毁
void SListDestory(Node* first)
{
	Node* next;
	for (Node* cur = first; cur != NULL; cur = next)
	{
		next = cur->next;
		free(cur);
	}
}

//头插
void SListPushFront(Node** pFirst, int v)
{
	Node* node = (Node*)malloc(sizeof(Node));

	node->value = v;
	node->next = *pFirst;
	*pFirst = node;
}

//头删
void SListPopFront(Node** pFirst)
{
	assert(*pFirst != NULL);

	Node* next = (*pFirst)->next;
	free(*pFirst);

	*pFirst = next;
}

//尾插
void SListPushBack(Node** pFirst, int v)
{
	//链表中没有元素的情况
	if (*pFirst == NULL)
	{
		Node* node = (Node*)malloc(sizeof(Node));
		node->value = v;

		node->next = *pFirst;
		*pFirst = node;
		return;
	}
	//链表中有很多值的情况
	Node* cur = *pFirst;
	while (cur->next)
	{
		//让Node指针指向链表中最后一个元素的地址
		cur = cur->next;
	}
	Node* node = (Node*)malloc(sizeof(Node));
	node->value = v;

	node->next = NULL;
	cur->next = node;
}

//尾删
void SListPopBack(Node** pFirst)
{
	assert(*pFirst != NULL);

	//链表中只有一个元素
	if ((*pFirst)->next == NULL)
	{
		free(*pFirst);
		*pFirst = NULL;
		return;
	}
	//多个元素
	Node* cur = *pFirst;
	while (cur->next->next)
	{
		cur = cur->next;
	}
	free(cur->next);
	cur->next = NULL;
}

//指定位置后插
// pos 肯定是链表中的结点
void SListInsertAfter(Node* pos, int v)
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->value = v;
	node->next = pos->next;
	pos->next = node;
}

//指定位置的后面元素删
// pos 肯定是链表中的结点
void SListEraseAfter(Node* pos)
{
	Node* next = pos->next;
	pos->next = pos->next->next;
	free(next);
}

//指定值查找
Node* SListFind(Node* first, int v)
{
	for (Node* cur = first; cur != NULL; cur = cur->next)
	{
		if (cur->value == v)
		{
			return cur;
		}
	}

	return NULL;
}

//删除第一个遇到的指定值v
void SListRemove(Node** pFirst, int v)
{
	assert(*pFirst != NULL);
	Node* cur = *pFirst;
	if (cur->value == v)
	{
		Node* second = cur->next;
		free(cur);
		cur = second;
	}
	else
	{
		Node* prev = NULL;
		while (cur && cur->value != v)
		{
			prev = cur;  //循环结束时保存的是v前面结、点的地址
			cur = cur->next;   //循环结束时保存的是v结点的位置
		}

		prev->next = cur->next; //让v前面结点的next等于v的next
		free(cur);         //释放cur
		cur = prev->next;  //cur指向 它后面结点的地址
		
	}
}

//删除遇到的所有指定值v
void SListRemoveAll(Node** pFirst, int v)
{
	assert(*pFirst != NULL);
	Node* cur = *pFirst;
	Node* prev = cur->next;
	//如果链表中只有一个节点且等于v
	if (cur->value == v && cur->next == NULL)
	{
		free(cur);
		cur = NULL;
		return;
	}
	
	while (prev) //遍历让cur一直循环到最后一个节点
	{
		//cur没到最后一个节点,且prev节点值等于v时进入循环
		while(prev != NULL && prev->value == v)
		{
			//删除指定节点cur后面的值
			cur->next = prev->next;
			free(prev);
			prev = cur->next; //更新新的prev
		}
		if (prev == NULL)
		{
			return; //循环到最后一个节点退出
		}
		cur = cur->next;  //进入下层循环
		prev = prev->next;
	}
}

//统计链表中的元素个数
int GetListLength(Node* first)
{
	int count = 0;
	if (first == NULL)
	{
		return 0;
	}
	Node* cur = first;
	while (cur)
	{
		count++;
		cur = cur->next;
	}
	return count;
}

//打印链表中所有数字元素
void SListPrint(Node* first)
{
	if (first == NULL)
	{
		printf("链表为空!\n");
		return;
	}
	Node* cur = first;
	printf("链表中的值为:\n");
	while (cur)
	{
		printf("%d\t", cur->value);
		cur = cur->next;
	}
	printf("\n");
}

3.主测试程序

测试程序

main.c

#include "SList.h"

void test()
{
	SListPushFront(&first, 1);
	// 1 -> NULL
	SListPushFront(&first, 2);
	// 2 -> 1 -> NULL
	SListPushFront(&first, 3);
	// 3 -> 2 -> 1 -> NULL
	SListPushFront(&first, 4);
	// 4 -> 3 -> 2 -> 1 -> NULL
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));

	SListPushBack(&first, 10);
	SListPushBack(&first, 20);
	SListPushBack(&first, 30);
	SListPushBack(&first, 40);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));

	// 4 3 2 1 10 20 30 40
	
	SListPopBack(&first);
	SListPopBack(&first);
	SListPopBack(&first);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));

	// 4 3 2 1 10
	SListPopFront(&first);
	SListPopFront(&first);
	SListPopFront(&first);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));

	// 1 10
	SListPopBack(&first);
	SListPopBack(&first);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));
	// first == NULL
	
}

void test1()
{
	SListPushFront(&first, 1);
	// 1 -> NULL
	SListPushFront(&first, 2);
	// 2 -> 1 -> NULL
	SListPushFront(&first, 3);
	// 3 -> 2 -> 1 -> NULL
	SListPushFront(&first, 4);
	// 4 -> 3 -> 2 -> 1 -> NULL
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));

	SListRemove(&first, 2);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));
}

void test2()
{
	SListPushBack(&first, 10);
	SListPushBack(&first, 20);
	SListPushBack(&first, 30);
	SListPushBack(&first, 20);
	SListPushBack(&first, 40);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));


	SListRemoveAll(&first, 20);
	SListPrint(first);
	printf("链表中元素总个数为:%d\n", GetListLength(first));
}

int main()
{
	Node* first;
	SListInit(&first);

	//头插 尾插 头删 尾删
	//test();

	//删除第一个遇到的v
	//test1();

	//删除链表中所有v
	test2();

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43892328/article/details/88879766
今日推荐