一步一步写算法(之通用算法的编写)

原文:一步一步写算法(之通用算法的编写)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

前面我们写过各种各样的算法,什么排序、查找、二叉树、队列、堆栈等等。但是我们在编写这些代码的时候却都有一个缺点,不知道大家发现了没有?那就是这些算法中使用的数据结构都是简单的int数据。所以,如果排序的是int,那么用起来没有什么问题。关键就是万一是其他的数据类型,那我们应该怎么办呢?

在c++中,有一种解决的方法。那就是类函数。就拿冒泡排序来说,我们完全可以这么写。

template <typename type>
void bubble_sort(type array[], int length)
{
	int outer;
	int inner;
	type median;

	if(NULL == array || 0 == length)
		return;

	for(outer = length -1; outer >0; outer --){
		for(inner = 0; inner < outer; inner ++){
			if(array[inner] > array[inner +1]){
				median = array[inner];
				array[inner] = array[inner +1];
				array[inner +1] = median;
			}
		}
	}

	return;
}

当然,如果是一个class需要调用上面的算法的话,它还需要定义type缺省构造函数、type拷贝够构造函数两个函数。

那么,在c语言里面有没有什么办法呢?其实也有,那就是void*这种方法。

void bubble_sort(void* array[], int length, int (*compare)(void*, void*), void(*swap)(void*, void*))
{
	int outer;
	int inner;

	for(outer = length -1; outer >0; outer --){
		for(inner = 0; inner < outer; inner ++){
			if(compare(array[inner], array[inner + 1]))
				swap(array[inner], array[inner + 1]);
		}
	}

	return;
}

接着在具体应用的时候,只需要将void*转换成自己需要的那个数据指针了。比如说,如果是int排序的话,我们就需要添加这两个函数即可。

int compare(void* var1, void* var2)
{
	int* p_var1 = (int*)var1;
	int* p_var2 = (int*)var2;

	return (*p_var1 > *p_var2) ? 1 : 0;
}

void swap(void* var1, void* var2)
{
	int* p_var1 = (int*)var1;
	int* p_var2 = (int*)var2;
	int median;

	median = *p_var1;
	*p_var1 = *p_var2;
	*p_var2 = median;
}

函数调用如下所示,数据转换稍显麻烦。

void test()
{
	int array[5] = {1, 2, 4,3,5};
	int* p_array[5] = {&array[0], &array[1], &array[2], &array[3], &array[4]};
	bubble_sort((void**)p_array, 5, compare, swap);

	return;
}

总结:

(1)写通用函数之前需要写好特定类型的算法函数

(2)通用算法的关键就是怎么样把通用的内容和具体的数据类型比较分开来

(3)C++和C语言在通用算法各有各的方法,建议大家多多使用,特别是一些经常使用的函数。

时间: 2024-10-13 01:39:20

一步一步写算法(之通用算法的编写)的相关文章

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

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

一步一步写算法(之 算法总结)

原文:一步一步写算法(之 算法总结) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 自10月初编写算法系列的博客以来,陆陆续续以来写了几十篇.按照计划,还有三个部分的内容没有介绍,主要是(Dijkstra算法.二叉平衡树.红黑树).这部分会在后面的博客补充完整.这里主要是做一个总结,有兴趣的朋友可以好好看看,欢迎大家提出宝贵意见. (1) 排序算法 快速排序 合并排序 堆排序 选择排序 基数排序 冒泡排序 插入排序 希尔排序 链表排序

一步一步写算法(之哈夫曼树 下)

原文:一步一步写算法(之哈夫曼树 下) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题.但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计).所以,我们所要做的就是编写compare和swap两个函数.通用冒泡代码如下所示, void bubble_sort(void* array[], int le

第56件事 排行榜通用算法4步

自从跟随师傅学艺之后,也爱上了看书,比较好奇,各大电商网站的图书排行榜排名到底是依据什么因素或维度来排列的?怎么样的排名算法算是比较科学的呢?有没有比较通用的算法?师傅肯定有方法.还真是,咨询师傅后,得知还真有通用的排名算法. 通用型的排行榜算法一共分为四步:第一步明确影响排行榜的维度或因素:第二步将每个维度或因素的数值标准化:第三步确定每个维度或因素的权重比:第四步计算综合评分后进行排名. 我们以一个具体的实例来阐述一下.假设现在有20个苹果供用户白吃或试吃,游戏规则是团长通过微信好友或朋友圈

一步一步写算法(之递归和堆栈)

原文:一步一步写算法(之递归和堆栈) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 看过我前面博客的朋友都清楚,函数调用主要依靠ebp和esp的堆栈互动来实现的.那么递归呢,最主要的特色就是函数自己调用自己.如果一个函数调用的是自己本身,那么这个函数就是递归函数. 我们可以看一下普通函数的调用怎么样的.试想如果函数A调用了函数B,函数B又调用了函数C,那么在堆栈中的数据是怎么保存的呢? 函数A ^ 函数B | (地址递减) 函数C |

一步一步写算法(之双向链表)

原文:一步一步写算法(之双向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的博客我们介绍了单向链表.那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针.双向链表相比较单向链表,主要有下面几个特点: (1)在数据结构中具有双向指针 (2)插入数据的时候需要考虑前后的方向的操作 (3)同样,删除数据的是有也需要考虑前后方向的操作 那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下: (

一步一步写算法(之字符串查找 上篇)

原文:一步一步写算法(之字符串查找 上篇) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 字符串运算是我们开发软件的基本功,其中比较常用的功能有字符串长度的求解.字符串的比较.字符串的拷贝.字符串的upper等等.另外一个经常使用但是却被我们忽视的功能就是字符串的查找.word里面有字符串查找.notepad里面有字符串查找.winxp里面也有系统自带的字符串的查找,所以编写属于自己的字符串查找一方面可以提高自己的自信心,另外一方面在某

一步一步写算法(之合并排序)

原文:一步一步写算法(之合并排序) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面一篇博客提到的快速排序是排序算法中的一种经典算法.和快速排序一样,合并排序是另外一种经常使用的排序算法.那么合并排序算法有什么不同呢?关键之处就体现在这个合并上面. 合并算法的基本步骤如下所示: 1)把0~length-1的数组分成左数组和右数组 2)对左数组和右数组进行迭代排序 3)将左数组和右数组进行合并,那么生成的整个数组就是有序的数据数组 下面

一步一步写算法(之排序二叉树)

原文:一步一步写算法(之排序二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent; str