19.1 C语言链表 -- 简单

链表节点(Node)

在C语言中,链表节点(Node)是构建链表数据结构的基本单元。每个结点包含两个核心部分:数据域合指针域

静态链表

静态链表的特定主要创建在栈区

复制代码
#include "stdio.h"
#include "linked_list.h"

struct linkNode {
	int num;
	struct linkNode* next;
};

//静态链表
void static_list_table() {
	struct linkNode node01 = {10 , NULL};
	struct linkNode node02 = {20 , NULL};
	struct linkNode node03 = {30 , NULL};
	struct linkNode node04 = {40 , NULL};
	struct linkNode node05 = {50 , NULL};

	//静态链表建立关系
	node01.next = &node02;
	node02.next = &node03;
	node03.next = &node04;
	node04.next = &node05;

	//打印数据
	struct linkNode* curruntNode = &node01;
	while (curruntNode != NULL) {
		printf("%d\n", curruntNode->num);

		//移动下一个位置
		curruntNode = curruntNode->next;
	}
}

void test_01_mian() {
	static_list_table();
}

动态链表

动态链表的特定主要创建在堆区

复制代码
#include "stdio.h"
#include "linked_list.h"

struct linkNode {
	int num;
	struct linkNode* next;
};

//动态链表
void dynamic_list_table() {
	
	//堆区创建节点
	struct linkNode* node01 = malloc(sizeof(struct linkNode));
	struct linkNode* node02 = malloc(sizeof(struct linkNode));
	struct linkNode* node03 = malloc(sizeof(struct linkNode));
	struct linkNode* node04 = malloc(sizeof(struct linkNode));
	struct linkNode* node05 = malloc(sizeof(struct linkNode));

	//数据赋值
	node01->num = 10;
	node02->num = 20;
	node03->num = 30;
	node04->num = 40;
	node05->num = 50;

	//建立关系
	node01->next = node02;
	node02->next = node03;
	node03->next = node04;
	node04->next = node05;

	//遍历节点
	struct linkNode* currentNode = node01;
	while (currentNode != NULL) {
		printf("%d\n",currentNode->num);
		
		//移动下一个位置
		currentNode = currentNode->next;
	}

	//释放内存
	free(node01);
	free(node02);
	free(node03);
	free(node04);
	free(node05);
}

void test_01_mian() {
	dynamic_list_table();
}

链表分类

带头和不带头列表

带头链表:就是头部创建一个头结点,接结点保持不变,起到一个标志性作用,不管后面结点如何变化,头结点始终不变

不带头链表:头结点不固定,根据实际需要更换头结点,在原来头结点中插入新节点,新节点作为头结点

链表初始化操作

复制代码
#include "stdio.h"
#include "linked_list.h"

struct linkNode{
	int num;
	struct linkNode* next;
};


//创建一个初始化结点
struct linkNode* initNode() {
	struct linkNode*  pHead = malloc(sizeof(struct linkNode));
	if (pHead == NULL) {
		printf("初始化失败,内存分配失败\n");
		return NULL;
	}

	//带头结点赋值
	pHead->next = NULL;//带头结点只维护指针域,不维护数据域

	//创建一个尾结点
	struct linkNode* pTail = pHead;

	int var = -1; 
	while (1) {
		printf("请输入num 输入-1结束运行\n");
		scanf_s("%d",&var);
		if (var == -1) {
			printf("退出运行...\n");
			break;
		}

		struct linkNode* newNode = malloc(sizeof(struct linkNode));
		newNode->num = var;
		newNode->next = NULL;
		
		//建立关系
		pTail->next = newNode;
		//更新尾结点
		pTail = newNode;
	}

	return pHead;
}


//循环打印链表
void foreach_ListNode(struct linkNode* head) {

	if (head == NULL) {
		return;
	}

	struct linkNode* currenNode = head->next;

	while (currenNode != NULL) {
		printf("%d\n", currenNode->num);

		currenNode = currenNode->next;
	}
}

void test_01_mian() {
	struct linkNode * head = initNode();
	foreach_ListNode(head);
}

链表插入操作

复制代码
#include "stdio.h"
#include "linked_list.h"


struct linkNode {
	int num;
	struct linkNode* next;
};

//创建一个初始化结点
struct linkNode* initNode() {
	struct linkNode*  pHead = malloc(sizeof(struct linkNode));
	if (pHead == NULL) {
		printf("初始化失败,内存分配失败\n");
		return NULL;
	}

	//带头结点赋值
	pHead->next = NULL;//带头结点只维护指针域,不维护数据域

	//创建一个尾结点
	struct linkNode* pTail = pHead;

	int var = -1; 
	while (1) {
		printf("请输入num 输入-1结束运行\n");
		scanf_s("%d",&var);
		if (var == -1) {
			printf("退出运行...\n");
			break;
		}

		struct linkNode* newNode = malloc(sizeof(struct linkNode));
		newNode->num = var;
		newNode->next = NULL;
		
		//建立关系
		pTail->next = newNode;
		//更新尾结点
		pTail = newNode;
	}

	return pHead;
}


//循环打印链表
void foreach_ListNode(struct linkNode* head) {

	if (head == NULL) {
		printf("循环打印失败传输指针为空\n");
		return;
	}

	struct linkNode* currenNode = head->next;

	while (currenNode != NULL) {
		printf("%d\n", currenNode->num);

		currenNode = currenNode->next;
	}
}

/*
* 插入链表
* 逻辑,首先找到原始数据,前后插入,需要记录上一个节点的记录
*/
void insert_list_node(struct linkNode* head,int oldNum,int newNum) {
	if (head == NULL) {
		printf("插入失败传输指针为空\n");
		return;
	}

	struct linkNode* pCurrent = head->next;
	struct linkNode* pPer = head;

	while (pCurrent != NULL) {

		//匹配数据
		if (pCurrent->num == oldNum) {
			break;
		}

		//如果没有比配需要建立关系
		pPer = pCurrent;
		pCurrent = pCurrent->next;
	}

	//新建一个节点
	struct linkNode * newNode = malloc(sizeof(struct linkNode));
	newNode->num = newNum;
	newNode->next = NULL;
	
	//建立关系
	newNode->next = pCurrent;
	pPer->next = newNode;

}

void test_02_mian() {

	//初始化节点
	struct linkNode * head = initNode();
	//打印节点数据
	foreach_ListNode(head);

	//往前插入
	insert_list_node(head, 10, 100);
	insert_list_node(head, 20, 200);
	insert_list_node(head, 30, 300);
	foreach_ListNode(head);
}

清空和销毁链表

复制代码
#include "stdio.h"
#include "linked_list.h"


struct linkNode {
	int num;
	struct linkNode* next;
};

//创建一个初始化结点
struct linkNode* initNode() {
	struct linkNode*  pHead = malloc(sizeof(struct linkNode));
	if (pHead == NULL) {
		printf("初始化失败,内存分配失败\n");
		return NULL;
	}

	//带头结点赋值
	pHead->next = NULL;//带头结点只维护指针域,不维护数据域

	//创建一个尾结点
	struct linkNode* pTail = pHead;

	int var = -1; 
	while (1) {
		printf("请输入num 输入-1结束运行\n");
		scanf_s("%d",&var);
		if (var == -1) {
			printf("退出运行...\n");
			break;
		}

		struct linkNode* newNode = malloc(sizeof(struct linkNode));
		newNode->num = var;
		newNode->next = NULL;
		
		//建立关系
		pTail->next = newNode;
		//更新尾结点
		pTail = newNode;
	}

	return pHead;
}


//循环打印链表
void foreach_ListNode(struct linkNode* head) {

	if (head == NULL) {
		printf("循环打印失败传输指针为空\n");
		return;
	}

	struct linkNode* currenNode = head->next;

	while (currenNode != NULL) {
		printf("%d\n", currenNode->num);

		currenNode = currenNode->next;
	}
}

/*
* 插入链表
* 逻辑,首先找到原始数据,前后插入,需要记录上一个节点的记录
*/
void insert_list_node(struct linkNode* head,int oldNum,int newNum) {
	if (head == NULL) {
		printf("插入失败传输指针为空\n");
		return;
	}

	struct linkNode* pCurrent = head->next;
	struct linkNode* pPer = head;

	while (pCurrent != NULL) {

		//匹配数据
		if (pCurrent->num == oldNum) {
			break;
		}

		//如果没有比配需要建立关系
		pPer = pCurrent;
		pCurrent = pCurrent->next;
	}

	//新建一个节点
	struct linkNode * newNode = malloc(sizeof(struct linkNode));
	newNode->num = newNum;
	newNode->next = NULL;
	
	//建立关系
	newNode->next = pCurrent;
	pPer->next = newNode;

}

/*
* 删除链表中节点
*/
void delete_list_node(struct linkNode * head,int num) {
	if (head == NULL) {
		printf("删除失败节点为空\n");
		return;
	}

	struct linkNode* pCurrent = head;
	struct linkNode* pPrev = pCurrent;

	//循环遍历
	while (pCurrent != NULL) {
		if (pCurrent->num == num) {
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}

	//判断一下是否有对应数据节点
	if (pCurrent == NULL) {
		printf("没有删除的结点\n");
		return;
	}

	//删除节点建立关系
	pPrev->next = pCurrent->next;

	//删除节点
	free(pCurrent);
	pCurrent = NULL;

}

/*
* 清空节点
* 清除后还可以往后,插入结点,链表还是可用的
*/
void clean_linkNode(struct linkNode *head) {
	if (head == NULL) {
		printf("清空链表失败\n");
		return;
	}

	struct linkNode* pCurrent = head->next;
	while (pCurrent != NULL) {
		struct linkNode* pNext = pCurrent->next;

		//释放当前节点
		free(pCurrent);

		//把下一个节点赋值给当前节点。这一步是方便下次循环利用
		pCurrent = pNext;
	}

	//头节点设置空
	head->next = NULL;
}

/*
* 销毁节点
*/
void destroy_linkNode(struct linkNode* head) {
	if (head == NULL) {
		printf("销毁链表失败\n");
		return;
	}
	//先清空链表
	clean_linkNode(head);

	//在释放头节点
	free(head);
	head = NULL;
}

void test_02_mian() {

	//初始化节点
	printf("=====================start===========================\n");
	printf("=====================初始化===========================\n");
	struct linkNode * head = initNode();
	//打印节点数据
	foreach_ListNode(head);

	printf("=====================往前插入===========================\n");
	//往前插入
	insert_list_node(head, 10, 100);
	insert_list_node(head, 20, 200);
	insert_list_node(head, 30, 300);
	foreach_ListNode(head);

	printf("======================删除节点==========================\n");
	//删除节点
	delete_list_node(head, 10);
	delete_list_node(head, 300);
	foreach_ListNode(head);

	printf("======================清除节点==========================\n");
	//清除节点
	clean_linkNode(head);
	foreach_ListNode(head);
	printf("=======================清除节点后再插入=========================\n");
	insert_list_node(head, 300, 3000);
	insert_list_node(head, 400, 4000);
	foreach_ListNode(head);

	printf("=======================end=========================\n");

}
相关推荐
阿正的梦工坊1 小时前
【Rust】07-错误处理:Option、Result 与 ? 运算符
开发语言·算法·rust
Zella折耳根2 小时前
复习篇-继承和接口
java·开发语言·python
z落落2 小时前
C# 事件(Event)+自定义带参数事件例子
开发语言·分布式·c#
FlYFlOWERANDLEAF2 小时前
DevExpress Office File API使用记录
开发语言·c#·devoffice
程序员二叉2 小时前
【JVM】OOM详解+JVM参数+FullGC排查+CPU飙高+死锁+内存泄漏+命令大全
java·开发语言·jvm·面试
yijianace2 小时前
Python线程与多线程完全总结(从入门到理解并发本质)
开发语言·python
不知名的老吴2 小时前
线程的生命周期之线程同步
java·开发语言·jvm
努力努力再努力wz3 小时前
【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解
linux·c语言·数据结构·数据库·c++·qt·链表
J2虾虾3 小时前
C 语言 void 完全用法
c语言·开发语言
会Tk矩阵群控的小木3 小时前
基于Python的iMessage短信群发与社媒多账号统一管理系统实现
开发语言·windows·python·新媒体运营·开源软件·个人开发