【由浅入深C系列二】通过一个链表开始

本文介绍了如何在C语言中定义一个链表数据结构,包括创建节点、设置节点值、遍历链表以及对代码进行优化的方法。通过示例代码展示了如何构建一个环形链表,并提供了完整的源代码文件。

简单链表的数据结构

要在C语言中使用链表,首先从定义一个链表开始。链表中通常包含节点,节点中有节点的值和指向下一个节点的指针。
如下的代码示例定义了一个1)包含指向下一个节点指针的,2)包含一个整型index和16个字节长度字符串name的节点的结构体。

typedef struct linked_list_s {
	struct linked_list_s *p_next;    // 指向链表中的下一个节点
	int index;
	char name[16];
} linked_list;

其中,typedef是C语言中的关键字,相当于把这个结构体起了一个简单的名字叫做linked_list。后续的代码可以将这个linked_list当一个新的“结构体类型”来用。

创建链表节点

这段代码比较简洁,主要作用是在内存中创建一个节点。malloc函数在<stdlib.h>头文件中(关于C语言中基本函数所在的头文件引用,可以参考我的上一篇文章 【由浅入深C系列一】C标准库(C99 )接口的头文件集和功能定义参考),包含这个文件即可以使用这个系统函数。

linked_list* create_node() {
	return (linked_list*)malloc(sizeof(linked_list));
}

设置链表结点

为了方便说明,通过注释在代码中进行说明。

linked_list* p_head = create_node();  // 头指针,指向链表的第一个元素
linked_list* p_cur = p_head;

p_cur->next = create_node(); // 依次创建4个节点,并对节点元素赋值
p_cur = p_cur->next;         // 将当前节点的指针指向,从头指针移向当前创建的新节点
p_cur->index = 1;            // 通过当前指针,对新节点进行赋值操作
strcpy(p_cur->name, "Test node");
p_cur->next = p_head;        // 将当前创建的新节点的下一个节点指向头指针,以确保为一个链表

p_cur->next = create_node();
p_cur = p_cur->next;
p_cur->index = 2;
strcpy(p_cur->name, "Test node");
p_cur->next = p_head;

p_cur->next = create_node();
p_cur = p_cur->next;
p_cur->index = 3;
strcpy(p_cur->name, "Test node");
p_cur->next = p_head;

p_cur->next = create_node();
p_cur = p_cur->next;
p_cur->index = 4;
strcpy(p_cur->name, "Test node");
p_cur->next = p_head;

遍历链表

通过一个循环,遍历链表中的每个节点,直到达到链表头。遍历过程中打印出:当前指针的地址,下一个节点指针的地址,当前节点的index和name值。

for (linked_list* p = p_head->p_next; p != p_head; p = p->p_next) {
	printf("[%x -> %x] %d %s\n", p, p->p_next, p->index, p->name);
}

运行结果

在这里插入图片描述

优化一下

把设置节点的语句抽出来重构成函数调用。

linked_list* set_node(const linked_list* head, linked_list* current, int index, char* name) {
	current->next = create_node(); // 当前节点的下一个节点指针,指向新创建的节点
	current = current->next;   // 当前指针前移,变成新创建的节点本身
	current->index = index;   // 以下二行是赋值
	strcpy(current->name, name);
	current->next = head;   // 新节点的下一个节点指针,指向头指针,链表变成环型
	return current;   // 返回新节点的指针
}

优化后的设置过程,代码简洁许多,逻辑也更加清晰。运行结果和上面一样,有兴趣的同学可以试试。

linked_list* p_head = create_node();
linked_list* p_cur = p_head;

p_cur = set_node(p_head, p_cur, 1, "Test node.");
p_cur = set_node(p_head, p_cur, 2, "Test node.");
p_cur = set_node(p_head, p_cur, 3, "Test node.");
p_cur = set_node(p_head, p_cur, 4, "Test node.");

完整的源代码文件

linked_list.h

#ifndef __LINKED_LIST_H__
#define __LINKED_LIST_H__


#include <stdlib.h>
/*--------------------------------------------------
	linked list methods.
--------------------------------------------------*/
#ifndef MAX_SHORT_NAME
#define MAX_SHORT_NAME 256
#endif

typedef struct linked_list_s {
	struct linked_list_s *next;
	int index;
	char name[MAX_SHORT_NAME];
} linked_list;

linked_list* create_node();

int set_node(const linked_list* head, int index, char* name);

linked_list* find(const linked_list* head, int index);

linked_list* get_last_node(linked_list* head);

int append_node(linked_list* head, int index, char* name);

int print_node(const linked_list* node);

#endif // _LINKED_LIST_H_

linked_list.c

/*--------------------------------------------------
	linked list methods.
--------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "../include/linked_list.h"

linked_list* create_node() {
	return (linked_list*)malloc(sizeof(linked_list));
}

linked_list* find(const linked_list* head, int index) {
	for (linked_list* p = head->next; p != head; p = p->next) {
		if (p->index == index)
		{
			return p;
		}
	}
}

int set_node(const linked_list* head, int index, char* name) {
	linked_list* p1 = find(head, index);
	strncpy(p1->name, name, MAX_SHORT_NAME);
	return 1;
}

linked_list* get_last_node(linked_list* head) 
{
	linked_list* last_node = head;
	for (linked_list* p = head->next; p != head; p = p->next)
		last_node = p;
	return last_node;
}

int append_node(linked_list* head, int index, char* name) {
	linked_list* last_node = get_last_node(head);
	linked_list* p_new = create_node();
	last_node->next = p_new;
	p_new->next = head;
	p_new->index = index;
	strncpy(p_new->name, name, sizeof(name));
	return 1;
}

int print_node(const linked_list* node) {
	return printf("[%s %s] [%x] next-> [%x] index:%d name:%s\n", __DATE__, __TIME__, node, node->next, node->index, node->name);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

招财猫_Martin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值