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

最近在阅读一个开源的C++代码,里面用到了大量的STL里面的东西。也许是自己一直用C而很少用C++来实现算法的原因,STL里面大量的模板令人心烦。一直对STL的效率表示怀疑,但在网上搜到这样一个帖子,说C的标准库里面快速排序比STL的标准排序要慢!于是,便认真的看了下二者的源码,发现C++里面的std::sort综合运用了部分快速排序和堆排序算法,而C标准库里面用的是通用数据结构的快速排序,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的大小是一样的。经过本人测试,随便一个特定数据结构的快速排序递归实现,都比c++ stl里面的std::sort要快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
16进制10进制.txt 32.txt asm.txt Crctable.txt C标志符命名源程序.txt erre.txt erre2.txt ff.txt for循环的.txt list.log N皇后问题回溯算法.txt ping.txt re.txt source.txt winsock2.txt ww.txt 万年历.txt 万年历的算法 .txt 乘方函数桃子猴.txt 乘法矩阵.txt 二分查找1.txt 二分查找2.txt 二叉排序树.txt 二叉树.txt 二叉树实例.txt 二进制数.txt 二进制数2.txt 余弦曲线.txt 余弦直线.txt 傻瓜递归.txt 冒泡排序.txt 冒泡法改进.txt 动态计算网络最最短路线.txt 十五人排序.txt 单循环链表.txt 单词倒转.txt 单链表.txt 单链表1.txt 单链表2.txt 单链表倒序.txt 单链表的处理全集.txt 双链表正排序.txt 反出字符.txt 叠代整除.txt 各种排序法.txt 哈夫曼算法.txt 哈慢树.txt 四分砝码.txt 四塔1.txt 四塔2.txt 回文.txt 图.txt 圆周率.txt 多位阶乘.txt 多位阶乘2.txt 大加数.txt 大小倍约.txt 大整数.txt 字符串查找.txt 字符编辑.txt 字符编辑技术(插入和删除) .txt 完数.txt 定串.txt 实例1.txt 实例2.txt 实例3.txt 小写数字转换成大写数字1.txt 小写数字转换成大写数字2.txt 小写数字转换成大写数字3.txt 小字库DIY-.txt 小字库DIY.txt 小孩分糖果.txt 小明买书.txt 小白鼠钻迷宫.txt 带头结点双链循环线性表.txt 平方根.txt 建树和遍历.txt 建立链表1.txt 扫描码.txt 挽救软盘.txt 换位递归.txt 排序法.txt 推箱子.txt 数字移动.txt 数据结构.txt 数据结构2.txt 数据结构3.txt 数组完全单元.txt 数组操作.txt 数组递归退出.txt 数组递归退出2.txt 文件加密.txt 文件复制.txt 文件连接.txt 无向图.txt 时间陷阱.txt 杨辉三角形.txt 栈单元加.txt 栈操作.txt 桃子猴.txt 桶排序.txt 检出错误.txt 检测鼠标.txt 汉字字模.txt 汉诺塔.txt 汉诺塔2.txt 灯塔问题.txt 猴子和桃.txt 百鸡百钱.txt 矩阵乘法动态规划.txt 矩阵转换.txt 硬币分法.txt 神经元模型.txt 穷举搜索法.txt 符号图形.txt 简单数据库.txt 简单计算器.txt 简单逆阵.txt 线性顺序存储结构.txt 线索化二叉树.txt 绘制圆.txt 编随机数.txt 网络最短路径Dijkstra算法.txt 自我复制.txt 节点.txt 苹果分法.txt 螺旋数组1.txt 螺旋数组2.txt 试题.txt 诺汉塔画图版.txt 读写文本文件.txt 货郎担分枝限界图形演示.txt 货郎担限界算法.txt 质因子.txt 输出自已.txt 迷宫.txt 迷宫问题.txt 逆波兰计算器.txt 逆矩阵.txt 逆阵.txt 递堆法.txt 递归桃猴.txt 递归车厢.txt 递推.txt 逻辑移动.txt 链串.txt 链栈.txt 链表十五人排序.txt 链表(递归).txt 链队列.txt 队列.txt 阶乘递归.txt 阿姆斯特朗数.txt 非递归.txt 顺序栈.txt 顺序表.txt 顺序队列.txt 骑士遍历1.txt 骑士遍历2.txt 骑士遍历回逆.txt 黑白.txt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值