【C 语言】链表(单结构体)

背景

  • 链表可以看作是可变数组的另外一种实现,通过指向新空间的方式,减少内存浪费,以及不用拷贝旧数据。
  • 通过自定函数封装相关功能,方便使用。
  • 单结构体,即只自定了节点结构体(Node)
  • 本文中的具体实现参考了浙大翁恺老师的 C 语言课程,链接已在本文末尾给出,如果有地方看不懂可以自己去看视频了解或者私信我。

结构定义及相关函数声明(linked_list.h)

#ifndef __LINKED_LIST_H
#define __LINKED_LIST_H

typedef struct Node {
	int value_;
	struct Node *next_;
} Node;

void node_Add(Node **head, int value);	//	添加节点
void node_Delete(Node *head, int target);	// 删除节点
void node_Set(Node *node, int value);	// 设置节点数据
Node* node_Search(Node *head, int target);	// 搜索节点,并获得地址
void node_Linked_List_Print(Node *head);	// 打印链表中的所有节点数据
void node_Linked_List_Clear(Node *head);	// 清除整个链表

#endif

函数定义(linked_list.c)

#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

void node_Add(Node **head, int value){	//	添加节点
/*
	因为最开始 head = NULL,所以使用 *head 会导致 *head = tp = NULL,此时就无法在函数内
	通过 head、tp 来修改外部的 head。
	当使用 **head 时,tp = NULL、head = 外部 head 指针的地址,此时便可以通过 *head = new_node
	使得外部的 head = new_node。
	有关 ** 与 * 的区别及相关案例,详见 https://blog.csdn.net/qq_64100889/article/details/137099357
*/

	Node *new_node = (Node*)malloc(sizeof(Node)), *tp = *head;
	new_node -> value_ = value;
	new_node -> next_ = NULL;

	if (*head == NULL) { // 开始头节点为空,不能通过指针访问,所以要特殊处理
		*head = new_node;	
	} else {
		while (tp -> next_ != NULL) { // 遍历列表,使指针指向尾节点
			tp = tp -> next_;	
		}
		tp -> next_ = new_node;
	}
}

void node_Delete(Node **head, int target) {	// 删除节点
	
	Node *tp = *head, *fp = (*head) -> next_;

	if ((*head) -> value_ == target) {
		*head = (*head) -> next_;
		free(tp);
	} else {
		for ( ; fp; tp = tp -> next_, fp = fp -> next_) {
			if (fp -> value_ == target) {
				tp -> next_ = fp -> next_;
				free(fp);
				break;
			}	
		}
	}
}


void node_Set(Node *node, int value) {	// 设置节点数据
	node -> value_ = value;
}

Node* node_Search(Node *head, int target) {	// 搜索节点

	for (Node *tp = head; tp; tp = tp -> next_) {
		if (tp -> value_ == target) {
			return tp;
		}
	}
	printf("当前节点不存在,请重试!(返回头节点地址)\n");
	return head;
}

void node_Linked_List_Print(Node *head) {	// 打印链表中的所有节点数据

	int i = 1;
	for (Node *tp = head; tp; tp = tp -> next_, i++) {
		
		printf("%d ", tp -> value_);

		if (i % 5 == 0) {
			printf("\n");
		}

	}

	printf("\n");		
}

void node_Linked_List_Clear(Node *head) {	// 清除整个链表

	Node *tp = head, *fp = tp -> next_;

	for ( ; fp; tp = fp, fp = fp -> next_) {
		free(tp);	
	}

	free(fp);
}

测试(main.c)

#include <stdio.h>
#include "linked_list.h"

int main() {

	Node *head = NULL;
	int number = 0, value = 0;

	while (1) {
		scanf("%d", &number);
		if (number == -1) {
			break;
		} else {
			node_Add(&head, number);
		}
	}

	printf("当前链表中的所有数据节点:\n");
	node_Linked_List_Print(head);

	printf("请输入要删除的数据节点:");
	scanf("%d", &number);
	node_Delete(&head, number);

	printf("请输入要设置的数据节点及数值:");
	scanf("%d %d", &number, &value);
	node_Set(node_Search(head, number), value);

	printf("当前链表中的所有数据节点:\n");
	node_Linked_List_Print(head);

	node_Linked_List_Clear(head);
	
	system("pause");

    return 0;
}


参考资料

C 语言程序设计进阶-翁恺

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值