单向有头不循环链表

链表是一种常见的基础数据结构,是一种线性表,是一种物理存储单元上非连续、非顺序的存储结构。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括存储数据元素的数据域和存储下一个结点地址的指针域两个部分。 相比于线性表顺序结构,操作复杂。数据元素的逻辑顺序也是通过链表中的指针链接次序实现的。

给出头文件:

#ifndef __SLIST_H__
#define __SLIST_H__

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

typedef int DataType;
typedef struct Node
{
	DataType data;        //数据域
	struct Node* next;	  //指针域
}Node;     //节点的结构体

//打印
void SListPrint(Node *pFirst);
// 初始化 
void SListInit(Node **ppFirst);
// 尾部插入 
void SListPushBack(Node** ppFirst, DataType data);
// 头部插入 
void SListPushFront(Node **ppFirst, DataType data);
// 尾部删除 
void SListPopBack(Node **ppFirst);
// 头部删除 
void SListPopFront(Node **ppFirst);
// 给定结点插入,插入到结点前 
void SListInsert(Node **ppFirst, Node *pos, DataType data);
// 给定结点删除 
void SListErase(Node **ppFirst, Node *pos);
// 按值删除,只删遇到的第一个 
void SListRemove(Node **ppFirst, DataType data);
// 按值删除,删除所有的 
void SListRemoveAll(Node **ppFirst, DataType data);
// 销毁 
void SListDestroy(Node **ppFirst);
// 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL 
int SListFind(Node *pFirst, DataType data);

#endif __SLIST_H__

接下来就实现如上功能

#include "SList.h"

void SListInit(Node **ppFirst)
{
	assert(ppFirst);
	*ppFirst = NULL;
}

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

Node* NewNode(DataType data)
{
	Node *node = (Node *)malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

//尾插
void SListPushBack(Node** ppFirst, DataType data)
{
	Node *node = NewNode(data);
	assert(ppFirst != NULL);
	if (*ppFirst == NULL) 
	{
		*ppFirst = node;
		return;
	}
	// 找链表中的最后一个结点	(链表中至少有一个结点)
	Node *cur = *ppFirst;
	while (cur->next != NULL) 
	{
		cur = cur->next;
	}
	cur->next = node;
}

//头插
void SListPushFront(Node **ppFirst, DataType data)
{
	assert(ppFirst != NULL);
	// 正常情况
	Node *node = NewNode(data);
	node->next = *ppFirst;
	*ppFirst = node;
}

//尾删
void SListPopBack(Node **ppFirst)
{

	assert(ppFirst != NULL);
	assert(*ppFirst != NULL);	// 链表不是空链表
	if ((*ppFirst)->next == NULL) {
		free(*ppFirst);
		*ppFirst = NULL;
		return;
	}
	// 链表中至少有两个结点,才能找倒数第二个
	Node *cur = *ppFirst;
	while (cur->next->next != NULL) {
		cur = cur->next;
	}
	free(cur->next);
	cur->next = NULL;
}

//头删
void SListPopFront(Node **ppFirst)
{
	assert(ppFirst != NULL);
	assert(*ppFirst != NULL);	// 链表不是空链表

	Node *first = *ppFirst;
	*ppFirst = (*ppFirst)->next;
	free(first);
}

// 给定结点插入,插入到结点前 
void SListInsert(Node **ppFirst, Node *pos, DataType data)
{
	if (*ppFirst == pos) {
		SListPushFront(ppFirst, data);
		return;
	}
	Node *newNode = NewNode(data);	// *** 不要忘了申请空间
	Node *cur;
	// 找到 pos 前的一个结点
	for (cur = *ppFirst; cur->next != pos; cur = cur->next) {}

	// 改变的是字段内的值,而不是指针的值
	cur->next = newNode;
	newNode->next = pos;
}

// 给定结点删除   (pos一定在链表中)
void SListErase(Node **ppFirst, Node *pos)
{
	if (*ppFirst == pos) {
		SListPopFront(ppFirst);
		return;
	}

	Node *cur = *ppFirst;
	while (cur->next != pos) {
		cur = cur->next;
	}
	cur->next = pos->next;
	free(pos);	// 不要忘记释放结点
}

// 按值删除,只删遇到的第一个 
void SListRemove(Node **ppFirst, DataType data)
{
	Node* node = NULL;
	Node* cur = NULL;
	node = *ppFirst;
	if (*ppFirst == NULL)
	{
		return;
	}
	else
	{
		while ((node->next)->data != data)
		{
			node = node->next;
		}
		cur = node->next;
		node->next = cur->next;
		free(cur);
	}
}

// 按值删除,删除所有的 
void SListRemoveAll(Node **ppFirst, DataType data)
{

	Node* node = NULL;
	Node* cur = NULL;
	node = *ppFirst;
	if (*ppFirst == NULL)
	{
		return;
	}
	else
	{
		while (node->next)
		{
			if ((node->next)->data == data)
			{
				cur = node->next;
				node->next = cur->next;
				free(cur);
				cur = NULL;
			}
			else
			{
				node = node->next;
			}
		}
		
	}
}

// 销毁 
void SListDestroy(Node **ppFirst)
{
	Node *cur, *next;
	for (cur = ppFirst; cur != NULL; cur = next) {
		next = cur->next;
		free(cur);
		cur = NULL;
	}
}

// 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL 
int SListFind(Node *pFirst, DataType data)
{
	for (Node *cur = pFirst; cur != NULL; cur = cur->next) {
		if (cur->data == data) {
			return cur;
		}
	}
	return NULL;
}

程序测试及结果如下:

#include "SList.h"

void test()
{
	Node* list = NULL;//初始化链表
	Node* pos = NULL;
	printf("前插后:\n");
	SListPushFront(&list, 1);
	SListPushFront(&list, 2);
	SListPushFront(&list, 3);
	SListPushFront(&list, 4);
	SListPushFront(&list, 5);
	SListPrint(list);
	
	printf("后插后:\n");
	SListPushBack(&list, 1);
	SListPushBack(&list, 2);
	SListPushBack(&list, 3);
	SListPushBack(&list, 4);
	SListPushBack(&list, 5);
	SListPrint(list);
	printf("前删和后删:\n");
	
	SListPopFront(&list);
	SListPopFront(&list);
	SListPopBack(&list);
	SListPopBack(&list);
	SListPrint(list);
	//
	printf("插入到指定位置:\n");
	pos = SListFind(list, 2);
	SListInsert(&list, pos, 100);
	pos = SListFind(list, 3);
	SListInsert(&list, pos, 0);
	SListPrint(list);
	
	printf("删除指定位置:\n");
	pos = SListFind(list,1);
	SListErase(&list,pos );
	SListPrint(list);
	printf("按值删除,只删遇到的第一个:\n");
	SListRemove(&list, 3);
	SListPrint(list);
	printf("按值删除,只删所有:\n");
	SListRemoveAll(&list, 2);
	SListPrint(list);
	//printf("销毁链表!");
	//SListDestory(&list);

}


int main()
{
	test();
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值