20200117 数据结构和算法之双向链表共享的实现!

双向链表的结构体如下:

typedef struct  _dbLinkList{
 datetype data;
 _dbLinkList* pre;
 _dbLinkList* next;
}dbLinkList,dbLinkNode;

其中的数据类型datatype根据实际情况,或者是普通的数据类型或者是自定义的结构体类型,这样datatpye 的不同,每种数据类型都要写相应的创、删、查、改、消函数,实际开发中会用到多个链表结构,这样做的工作量大,有没有一种比较轻便的方法,减少函数的开发,提高代码的可重用性呢?有,那就是“双向链表挂件”,将data从双向链表中剥离出来,其结构如下:

typedef struct  _dbLinkList{
 _dbLinkList* pre;
 _dbLinkList* next;
}dbLinkList,dbLinkNode;

同时根据实际需求,增加结构体定义

typede struct _connecTimeOut{
 int fd;
 time_t timeout;
 dbLinkList node;
}

结构体挂件定义好以后,有一个比较奇妙的方法通过双向链表的结点node,可以访问fd和timeout,这个函数就是 offsetof,获取结构体分量和对应分量的偏移量,这样就可以通过node的地址减去偏移量就可以获得connecTimeOut结构体的地址,进而访问对应的分量。不过在中间过程中涉及到强制类型转换。核心代码如下:

dbLinkList* p =&(ct->node);
int off = offsetof(connectTimeOut, node);
connectTimeOut* tmp = (connectTimeOut*)((size_t)p - off);

整个测试代码如下,双向链表的共享结构确实很方便,可以一个双向链表通吃天下。

#include<Windows.h>
#include<string>
#include<iostream>
using namespace std;
typedef struct _dbLinkList {
	_dbLinkList* pre;
	_dbLinkList* next;
}dbLinkListNode,dbLinkList;
typedef struct _connectTimeOut {
	int fd;
	time_t timeout;
	dbLinkList node;//双向链表的挂件
}connectTimeOut;
typedef struct _STAR {
	int x;
	int y;
	int step;
	int color;
	int radius;
	dbLinkList node;
}STAR;
bool initLinkListConnTimeOut(connectTimeOut* &ct) {
	if (!ct) return false;
	ct->fd = -1;
	ct->timeout = 0;
	ct->node.pre = NULL;
	ct->node.next = NULL;
	
	return true;
};
bool initLinkListStar(STAR* &star) {
	if (!star) return false;
	star->x = 0;
	star->y = 0;
	star->step = 0;
	star->radius = 0;
	star->color = 0;
	star->node.next = NULL;
	star->node.pre = NULL;
	return true;
}
bool dbLinkListInsertBack(dbLinkList &link, dbLinkList &node) {	
	dbLinkList* p = &link;
	while (p->next != NULL) {
		p = p->next;
	}
	p->next = &node;
	node.pre = p;
	node.next = NULL;
	return true;
};

int main() {
	connectTimeOut* ct = NULL;
	ct = new connectTimeOut;
	STAR* star = NULL;
	star = new STAR;


	//01 初始化
	initLinkListConnTimeOut(ct);
	initLinkListStar(star);
	//02-添加元素
	connectTimeOut* tmp = NULL;
	int cout;
	std::cout << "通过尾插法将数据插入双向链表中,请输入文件句柄个数:" << std::endl;
	cin >> cout;
	std::cout << "请依次输入文件句柄:";
	for (int i = 0; i < cout; i++) {
		tmp = new connectTimeOut;
		cin >> tmp->fd;
		dbLinkListInsertBack(ct->node,tmp->node);
	}
	//03-根据链表结点访问文件句柄
	dbLinkList* p = &(ct->node);
	
	std::cout << "通过双向链表结点来遍历访问文件句柄!" << std::endl;

	while (p->next) {	
		p = p->next;
		int off = offsetof(connectTimeOut, node);
		connectTimeOut* tmp =(connectTimeOut*) ((size_t)p - off);
		std::cout << tmp->fd<<" "<<p << std::endl;	
	}

	//04--销毁双向链表
	std::cout << "销毁双向链表的结点" << std::endl;
	p = &(ct->node);
	while (p) {
		int off = offsetof(connectTimeOut, node);
		connectTimeOut* tmp=(connectTimeOut*)((size_t)p - off);
		std::cout << tmp->fd << " " << p << std::endl;
		p = p->next;
		delete tmp;
	}


	/*connectTimeOut* ct = NULL;
	ct = new connectTimeOut;
	cout << "请输入一个fd的数据";
	cin >> ct->fd;
	dbLinkList* p =&(ct->node);
	int off = offsetof(connectTimeOut, node);
	connectTimeOut* tmp = (connectTimeOut*)((size_t)p - off);
	cout<<tmp->fd;*/

	system("pause");
	return 0;

}
发布了51 篇原创文章 · 获赞 0 · 访问量 526

猜你喜欢

转载自blog.csdn.net/weixin_40071289/article/details/104015173
今日推荐