单向链表及其应用(C语言)

本文详细介绍了单向链表的概念,并探讨了其在C语言中的具体应用,展示了如何利用链表来扩展进程地址空间并实现内存共享。

一、单向链表

//list.h
#ifndef LIST_H_
#define LIST_H_
#include <stdlib.h>

typedef struct ListElement_ {
	void *data;
	struct ListElement_ *next;
} ListElement;

typedef struct List_ {
	int size;
	int (*match) (const void *data1, const void *data2);
	void (*destory) (void* data);
	ListElement *head;
	ListElement *tail;
} List;

void list_init(List *list, void (*destory) (void *data));  //初始化链表,每次使用前都要去初始化
void list_destory(List *list);				  //销毁链表
int list_ins_next(List *list, ListElement *element, const void *data);  //在指定的元素画面插入一个元素,如果element为NULL,则在表头插入
int list_rem_next(List *list, ListElement *element, void *data);       //移除指定元素的后面一个元素
#define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list)	((list)->tail)
#define list_is_head(list, element) ((element) == (list->head) ? 1 : 0)
#define list_is_tail(element)		((element)->next == NULL ? 1 : 0)
#define list_data(element)			((element)->data)
#define list_next(element)			((element)->next)

#endif
实现文件list.c

#include "list.h"
#include 
#include 
#include 
void list_init(List *list, void (*destory)(void *data)) {
	if (list == NULL) return;
	list->size = 0;
	list->match = NULL;
	list->destory = destory;
	list->head = NULL;
	list->tail = NULL;
}

void list_destory(List *list) {
	if (list == NULL) return;
	void *data;
	while (list_size(list) > 0) {
		if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destory != NULL) {
			list->destory(data);
		}	
	}
	memset(list, 0, sizeof(list));
}

int list_ins_next(List *list, ListElement *elem, const void *data) {
	if (!list) return -1;
	ListElement *ins_elem = (ListElement*)malloc(sizeof(ListElement));
	list_data(ins_elem) = data;
	list_next(ins_elem) = NULL;
	if (!elem) {
		if (list_size(list) == 0)  list_tail(list) = ins_elem;
		list_next(ins_elem) = list_head(list);
		list_head(list) = ins_elem;
	} else {
		if (list_next(elem) == NULL) list_tail(list) = ins_elem;
		list_next(ins_elem) = list_next(elem);
		list_next(elem) = ins_elem;
	}
	list->size++;
	return 0;
}

int list_rem_next(List *list, ListElement *elem, void **data) {
	if (!list || list_size(list) == 0) return -1;
	ListElement *old_element;
	if (!elem) {
		*data = list_data(list_head(list));
		old_element = list_head(list);
		list_head(list) = list_next(list_head(list)); 
		
		if (list_size(list) == 1) list->tail = NULL;
	} else {
		if (elem->next == NULL) return -1;
		*data = list_data(list_next(elem));
		old_element = (list_next(elem));
		list_next(elem) = list_next(list_next(elem));
		
		if (elem->next == NULL) list->tail = elem;
	}
	free(old_element);
	list_size(list)--;
	return 0;
}


二、单向链表的应用

单向链表可以应用于操作系统的虚拟内存中,我们知道程序使用的内存空间大于实际的物理内存。虚拟内存是一种地址空间的映射机制,它允许进程不必完全加载到物理内存中也可以得到运行。这种方式的优点:
  1. 进程可以使用比系统实际所允许的物理内存大得多的地址空间。
  2. 多个进程能够共享系统的内存以并发的方式执行。
可以使用页表来实现虚拟内存的机制。每个进程都有它自己的页表,将它的虚拟地址空间中的页映射到物理内存中的页帧上。当某个进程引用一个虚拟地址时,页表中的某项需要检查并决定该页关联到哪个物理页帧上。

模拟内存页表的代码:
#include "list.h"
//从空闲的页帧链表中获取空闲页帧号
int alloc_frame(List *list) {
	if (list_size(list) == 0) return -1;
	int *frame_number;
	if (list_size(list)) {
		list_rem_next(list, NULL, (void**)&frame_number);
	}
	return *frame_number;
}

//接受一个页帧号并将其放回空闲页帧链表中
int free_frame(List *list, int frame_number) {
	int *data;
	
	if ((data = (int*)malloc(sizeof(int))) == NULL) return -1;
	
	*data = frame_number;
	
	if (list_ins_next(list, NULL, data))
		return -1;
	return 0;
}

void init_page(List *list) {
	int i;
	for (i = 0; i < 10; ++i) {
		int *j = (int*) malloc(sizeof(int));
		*j = rand() % 50;
		list_ins_next(list, NULL, j);
	}
}

void print(List *list) {
	int i = 0;
	ListElement *elem = list->head;
	printf("list size is : %d\n", list_size(list));
	for (; i < list_size(list) && elem != NULL ; ++i) {
		printf("%d\n", *(int*)elem->data);
		elem = elem->next;
	}
}

int real_mem[50] = {0,}; //模拟系统中真实的内存
	
int get_mem(int frame) {  //获取真实的内存值
	return real_mem[frame];
}
	
int main() {
	List *list = (List*)malloc(sizeof(*list));
	list_init(list, free);
	init_page(list);  //初始化一个页表
	print(list);
	int frame = alloc_frame(list);
	//取得了页帧号,获取真实的物理内存
	int use_mem = get_mem(frame);
	//TODO: 使用这块内存
	list_destory(list);
	return 0;
}




内容概要:本文针对高渗透率分布式光伏与储能变流器接入配电网所带来的运行挑战,深入研究了传统跟网型(GFL)逆变器在电网故障、弱电网及孤岛工况下易失稳脱网,以及构网型(GFM)虚拟同步发电机(VSG)逆变器在并网状态下缺乏同步调节能力的技术瓶颈,提出了一种可实现GFL与GFM双向平滑切换的先进控制策略。研究首先构建了GFL与GFM共用的硬件平台与内环控制基础,继而系统性地设计了基于关键电气量实时监测的切换判据、精确的双向切换时序逻辑,并创新性地引入了过渡过程的平滑抑制策略,以有效抑制切换瞬间的有功功率冲击、电压闪变与频率突变。全文在Matlab/Simulink环境中搭建了完整的仿真模型,通过对并网转孤岛、孤岛转并网等多种工况的动态仿真,全面验证了所提策略的有效性,结果表明该方法能确保系统在模式切换过程中电压、电流与频率的平稳过渡,显著提升了微电网在复杂运行条件下的韧性、稳定性与供电可靠性。; 适合人群:从事电力电子、新能源并网、微电网控制、智能配电网等领域的高校研究生、科研院所研究人员及电力系统相关企业的工程技术人员。; 使用场景及目标:① 解决高比例可再生能源接入引发的电网稳定性与电能质量问题;② 实现微电网在并网与孤岛两种运行模式间的无缝、可靠切换,保障重要负荷的不间断供电;③ 为构网型与跟网型逆变器的协同运行、新型电力系统构建提供先进的控制理论依据与可落地的技术解决方案。; 阅读建议:建议结合文中提供的Simulink仿真模型进行深入学习,重点剖析切换逻辑模块的设计原理与参数整定方法,通过反复观察和分析不同工况下的仿真波形,深刻理解平滑切换过程中的动态响应机理与控制思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值