当前位置: 首页 > article >正文

数据结构基础(不带头节点的单向非循环链表)

单链表完整代码

      • LinkList.h
      • LinkList.c
      • test.c

LinkList.h

#pragma once

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

typedef int ElemType;
typedef struct LNode {
	ElemType data;
	struct LNode* next;
}LNode;

void LinkListPrint(LNode* phead);
// 尾插
void LinkListPushBack(LNode** phead,ElemType x);
// 头插
void LinkListPushFront(LNode** phead, ElemType x);
// 尾删
void LinkListPopBack(LNode** phead);
// 头删
void LinkListPopFront(LNode** phead);
// 查找
LNode* LinkListFind(LNode* pphead, ElemType x);
// 在pos的前面插入x
void LinkListInsert(LNode** phead, LNode* pos, ElemType x);
// 删除pos位置的值
void LinkListErase(LNode** phead,LNode* pos);


 有些地方
 下标i的位置插入x
//void LinkListInsert(LNode** phead, int i, ElemType x);
 删除下标i位置的值
//void LinkListErase(LNode** phead, int i);

LinkList.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "LinkList.h"


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

// 尾插
void LinkListPushBack(LNode** pphead, ElemType x)
{
	// 申请一个要插入的节点(申请节点,实际开发注意事项)
	LNode* newNode = (LNode*)malloc(sizeof(LNode));
	if (newNode == NULL)// 申请节点失败,(VS报错:取消对 NULL 指针“newNode”的引用)
	{
		printf("%s", strerror(errno));// 将错误码转换成错误信息
	}
	else
	{
		newNode->data = x;
		newNode->next = NULL;
	}


	if (*pphead == NULL)// phead为空,直接把新节点赋给phead,
	{
		*pphead = newNode;
	}
	else// 至少有一个或多个,找到尾节点,链接新节点
	{
		// 找尾节点
		LNode* tail = *pphead;//
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		// 尾节点,链接新节点
		tail->next = newNode;
	}

}

// 头插
void LinkListPushFront(LNode** pphead, ElemType x)
{
	// 申请一个到插入的节点
	LNode* newNode = (LNode*)malloc(sizeof(LNode));
	newNode->data = x;
	newNode->next = NULL;

	// 将该节点指向头节点,第一个节点为空也不影响
	newNode->next = *pphead;
	*pphead = newNode;// 将新节点作为头节点
}

// 尾删
void LinkListPopBack(LNode** pphead)
{
	// 为空,没有节点
	// 只有一个节点,先释放再置为空,避免野指针
	// 有多个节点,找尾节点并创建一个节点找尾节点的前一个节点
	if (*pphead == NULL)
		return;
	else if ((*pphead)->next == NULL)// *的优先级比较低
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		LNode* prev = NULL;
		LNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}

}
// 头删
void LinkListPopFront(LNode** pphead)
{
	// 头删确保不为空,否则越界
	//assert(*pphead);
	if (*pphead == NULL)
		return;
	LNode* next = (*pphead)->next;// 申请一个节点指向头节点的下一个节点
	free(*pphead);// 释放头节点
	*pphead = next;
}
// 查找pos节点的位置
LNode* LinkListFind(LNode* pphead, ElemType x)
{
	LNode* cur = pphead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
// 在pos的前面插入x
void LinkListInsert(LNode** pphead, LNode* pos, ElemType x)
{
	// 如果pos是第一个位置,在第一个位置前面插入x(头插)
	// 否则找到pos的前一个节点
	if (pos == *pphead)
	{
		LinkListPushFront(pphead, x);
	}
	else
	{
		LNode* newNode = (LNode*)malloc(sizeof(LNode));// 申请一个要插入的节点
		newNode->data = x;
		newNode->next = NULL;

		LNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newNode;
		newNode->next = pos;
	}


}
// 删除pos位置的值
void LinkListErase(LNode** pphead, LNode* pos)
{
	// pos在第一个节点(头删)
	if (pos == *pphead)
	{
		LinkListPopFront(pphead);
	}
	else
	{
		LNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}

}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "LinkList.h"

// 二级指针存放(取出)的是一级指针的地址
void LinkListTest1()
{
	LNode* plist = NULL;// 结构体类型的指针,头指针
	LinkListPushBack(&plist, 1);
	LinkListPushBack(&plist, 2);
	LinkListPushBack(&plist, 3);
	LinkListPushBack(&plist, 4);
	LinkListPushFront(&plist, 0);// 要想改变一级指针应该传一级指针的地址,对一级指针解引用
	LinkListPrint(plist);

	LinkListPopFront(&plist);
	LinkListPopFront(&plist);
	LinkListPopFront(&plist);
	LinkListPopFront(&plist);
	LinkListPrint(plist);
	LinkListPopFront(&plist);
	LinkListPrint(plist);
	//LinkListPopFront(&plist);

}
void LinkListTest2()
{
	LNode* plist = NULL;// 结构体类型的指针,头指针
	LinkListPushBack(&plist, 1);
	LinkListPushBack(&plist, 2);
	LinkListPushBack(&plist, 3);
	LinkListPushBack(&plist, 4);
	LinkListPushFront(&plist, 0);// 要想改变一级指针应该传一级指针的地址,对一级指针解引用
	LinkListPrint(plist);

	LinkListPopBack(&plist);
	LinkListPopBack(&plist);
	LinkListPrint(plist);

	LinkListPopBack(&plist);
	LinkListPopBack(&plist);
	LinkListPrint(plist);

}
void LinkListTest3()
{
	LNode* plist = NULL;// 结构体类型的指针,头指针
	LinkListPushBack(&plist, 1);
	LinkListPushBack(&plist, 2);
	LinkListPushBack(&plist, 3);
	LinkListPushBack(&plist, 4);
	LinkListPushFront(&plist, 0);// 要想改变一级指针应该传一级指针的地址,对一级指针解引用
	LinkListPrint(plist);

	// 找到1,在1的前面插入30
	LNode* pos = LinkListFind(plist, 0);
	if (pos)
	{
		LinkListInsert(&plist, pos, 30);
	}
	LinkListPrint(plist);

}
void LinkListTest4()
{
	LNode* plist = NULL;// 结构体类型的指针,头指针
	LinkListPushBack(&plist, 1);
	LinkListPushBack(&plist, 2);
	LinkListPushBack(&plist, 3);
	LinkListPushBack(&plist, 4);
	LinkListPushFront(&plist, 0);// 要想改变一级指针应该传一级指针的地址,对一级指针解引用
	LinkListPrint(plist);

	LNode* pos = LinkListFind(plist, 0);
	if (pos)
	{
		LinkListErase(&plist, pos);
	}
	pos = LinkListFind(plist, 4);
	if (pos)
	{
		LinkListErase(&plist, pos);
	}
	//pos = LinkListFind(plist, 3);
	//if (pos)
	//{
	//	LinkListErase(&plist, pos);
	//}
	pos = LinkListFind(plist, 2);
	if (pos)
	{
		LinkListErase(&plist, pos);
	}
	//pos = LinkListFind(plist, 1);
	//if (pos)
	//{
	//	LinkListErase(&plist, pos);
	//}
	LinkListPrint(plist);

}
int main()
{
	//LinkListTest1();
	//LinkListTest2();
	LinkListTest4();

	return 0;
}

http://www.kler.cn/a/158753.html

相关文章:

  • 前端:HTML (学习笔记)【1】
  • Area-Composition模型部署指南
  • Java基础-Java中的常用类(上)
  • HarmonyOS 如何获取设备信息(系统、版本、网络连接状态)
  • 3356. 零数组变换 Ⅱ
  • 【c++笔试强训】(第十一篇)
  • NAS-DIP: Learning Deep Image Prior with Neural Architecture Search
  • 基于ssm vue的风景文化管理平台源码和论文
  • MicroPython 基于microdot框架搭建网页服务器
  • Oracle Flashback技术简介与快速入门
  • centos中mysql8忘记密码的操作步骤
  • JAVA 线程池,及7大参数,4大拒绝策略详解
  • 连接池 Druid (三) - 获取连接 getConnection
  • 【C++ protobuf中对不同消息内容进行赋值的方式】
  • Appium:iOS测试比Android测试更难?
  • Linux-hid
  • Shell数组函数:数组(二)
  • 继在统信UOS上运行.Net Core之后,保持其在后台运行,并出错自重启
  • Unity渲染Stats分析
  • 使用Docker在Debian上构建GRBL模拟器镜像:简明步骤和操作指南
  • C语言--每日选择题--Day36
  • 随机链表的复制[中等]
  • 服务器以及页面无报错,但是ajax一直回调error。怎么查找报错信息,更好地了解到底是什么问题导致了请求失败
  • Qt 大小端转换函数qFromBigEndian qFromLittleEndian
  • 【亲测有效,超详细】收到微信小程序限期完成微信认证通知怎么处理?微信小程序年审认证都需要哪些资料?
  • Flink之复杂事件处理CEP