C语言实现通用数据结构的高效设计

最近在阅读一个开源的C++代码,里面用到了大量的STL里面的东西。也许是自己一直用C而很少用C++来实现算法的原因,STL里面大量的模板令人心烦。一直对STL的效率表示怀疑,但在网上搜到这样一个帖子,说C的标准库里面快速排序比STL的标准排序要慢!于是,便认真的看了下二者的源码。其实两个使用的算法是完全类似的,而C标准库里面的qsort之所以比std::sort慢,是因为C语言中为了适配所有的数据结构使用了空指针。下面以更为简单的插入排序为例说明这个问题。

插入排序的算法实现代码:

void insert_sort(int a[], int n)
{
	int i, j;
	int t;
	for (i = 1; i < n; i++) {
		t = a[i];
		j = i;
		while ((j > 0) && (a[j - 1] > t)) {
			a[j] = a[j - 1];
			j--;
		}
		a[j] = t;
	}
}  

上述插入排序的实现只能针对整数类型进行排序,如果数据类型是浮点型,则要自己重新把代码拷贝一份,并且更改函数名以及数据类型。如果是双精度的,又或者是对自定义的结构体数组进行排序呢? 显然,这不是一种很好的解决方案。 而用空指针可以解决这个问题。

通用数据类型的插入排序实现代码:

void general_insert_sort(void* arr, int num_element, int element_bytes, int (*cmp_fun)(void* p1, void* p2))
{
	int i, j;
	int t[1024];
	if (element_bytes > 4096){
		return;
	}
#define ELE(arr, i) (void*)(((unsigned)arr) + (i) * element_bytes)
	for (i = 1; i < num_element; i++) {
		memcpy(t, ELE(arr, i), element_bytes);
		j = i;
		while ((j > 0) && (cmp_fun(ELE(arr, j - 1), (void*)t))) {
			memcpy(ELE(arr, j), ELE(arr, j - 1), element_bytes);
			j--;
		}
		memcpy(ELE(arr, j), (void*)t, element_bytes);
	}
} 

上述通用插入排序的实现有一个限制,就是待排序数组里面每一个元素的大小不能超过4k,当然对于简单的系统预定义好的数据类型,数组元素的大小最大为double,只有8个字节,这是远远的足够用的。如果你自定义的结构体的大小太大,例如大于这里设置的4K,则没有必要用此方法排序,因为此时数据移动会占用大部分时间,此时应该考虑用索引排序的方法。

上面的方法虽然解决了任意数据类型的问题,但是其效率并不怎么高。相对于上述第一段代码而言,简单的赋值语句必须得调用一个函数来拷贝数据,简单的比较语句,则需要调用外部传入一个函数指针得到比较结果。这是效率低下的根本原因。

而C++模板参数的出现,只需要写一份代码,编译器根据你调用时候的数据类型自动生成新的代码。其实用宏也可以完成通用的功能。这里给出C语言宏的代码,C++模板的代码也很简单。

#define FIV_IMPLEMENT_INSETT_SORT(function_name, T, LT_CMP)void function_name(T* arr, int low, int high){	int i, j;	T t;	for (i = low + 1; i < high; i++) {		t = arr[i];		j = i;		while ((j > low) && (LT_CMP(t, arr[j - 1]))) {			arr[j] = arr[j - 1];			j--;		}		arr[j] = t;	}} 

上面的宏定义可以看做是一种模板定义,可以用于任意数据类型。如果你要对整数进行排序,很简单,用下面的两个宏,一个宏定义比较运算,一个宏为函数定义:

#define  CMP(a, b)    ((a) < (b))
FIV_IMPLEMENT_INSETT_SORT(insert_sort_int, int, CMP)

这样就有一个用于整数排序的函数insert_sort_int可用,如果是你自定义的结构体类型,则同样只需要写这两个宏就可以了。

结尾:

用C++模板产生的代码大小是不使用模板的很多倍,而用C语言的空指针可以支持任意数据类型,代码大小很小,而用C语言的宏定义产生模板函数的代码大小理论上和使用STL的大小是一样的。

时间: 2024-10-17 00:39:44

C语言实现通用数据结构的高效设计的相关文章

一步一步写算法(之通用数据结构)

原文:一步一步写算法(之通用数据结构) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 上一篇博客介绍了通用算法,那么有了这个基础我们可以继续分析通用数据结构了.我们知道在c++里面,既有数据又有函数,所以一个class就能干很多事情.举一个简单的例子来说,我们可以编写一个数据的class计算类. class calculate{ int m; int n; public: calculate():m(0),n(0) {} calcula

Java语言编程学习之Lambda表达式设计和架构的原则[图]

Java语言编程学习之Lambda表达式设计和架构的原则[图]:大家都知道,Lambda表达式是对Java语言的一点简单改进,在JDK标准类库中,运行它的方式各种各样.但是大多数的Java代码都不是由开发JDK的程序猿写的,而是像我们这样的普通程序猿.很多人都会碰到过这样的情况:你实现了一个新功能或修复了一个缺陷,并且对自己的修改很满意.但其他人看了你的代码后--也许发生在代码审查环节,完全不买账!对于什么是好代码,什么是坏代码,存在分歧很正常!设计模式的改变设计模式是人们熟悉的另一种设计思想,

c语言 &lt;除法散列法&gt; 高效 HashTable Dictionary

c语言 <除法散列法> 高效 HashTable Dictionary  ,不管集合大小,任意长度根据key查询都只是一次寻址左右,so 最快时间复杂度为O1! 先上代码,明天写原理注释! HashDictionary.h #define CM_STR_HASHFUNC_CONSTANT 31 #define KEYSIZE 40 struct Entry { int hashCode; int next; char key[KEYSIZE]; void* value; }; struct H

C语言连接MySQL数据库(课程设计总结)

刚结束课程设计,也预示着假期马上就要到来了.本次课程设计并不算难,无非就是让做一个XXX系统,实现用户的注册.登录.菜单管理.超级用户等等一些功能,到现在为止已经做过好几个了,所以基本流程都熟悉了!我觉的最值得总结的地方就是:C语言与数据库连接,这块内容!因为之前都是用文件实现的. ★平台 这次课程设计主要用到: ● VC ++ 6.0 ● mysql-5.0.18-win32 ● Navicat for MySQL(MySQL 图形化的工具) ★配置 在写代码之前首先要让编译器知道MySQL数

Atitit. 脚本语言的断点单步调试的设计与实现 attialx 总结 php 参照java

Atitit. 脚本语言的断点单步调试的设计与实现 attialx 总结 php 参照java 1. 断点的实现:手动断点 die和exit是等价的 1 2. 变量表的实现 1 3. print_r(  $vars_list ); 1 4. print_r和var_dump都能输出数组和对象, 1 5. 参考 2 1. 断点的实现:手动断点 die和exit是等价的 2. 变量表的实现 $vars_list= array(); 放入变量表ui... global  $vars_list; $va

数据结构_课程设计——最小生成树:室内布线

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 这道课程设计,费不少时间,太麻烦了= =.(明明是能力不够) ~~~~最小生成树:室内布线~~~~ 题目要求: 装修新房子是一项颇为复杂的工程,现在需要写个程序帮助房主设计室内电线的布局. 首先,墙壁上插座的位置是固定的.插座间需要有电线相连,而且要布置的整齐美

数据结构_课程设计——并查集:检查网络

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 这两天做数据结构课程设计,因为以前做过ACM题,感觉还可以,不是很难呀 ~~~~并查集:检查网络~~~~ 题目要求: 给定一个计算机网络以及机器间的双向连线列表,每一条连线允许两端的计算机进行直接的文件传输,其他计算机间若存在一条连通路径,也可以进行间接的文件传

【转载】数据结构与算法设计

原文: 数据结构与算法设计

Cocos2d-x 脚本语言Lua基本数据结构-表(table)

table是Lua中唯一的数据结构,其他语言所提供的数据结构,如:arrays.records.lists.queues.sets等,Lua都是通过table来实现,并且在lua中table很好的实现了这些数据结构.--摘自:<Programming in Lua> 看以下代码,可以很清晰的明白Lua中表的使用: -- Lua中的表,table Config = {hello="Hello Lua",world="World"} -- 赋值方式1,以键=