哨兵节点

1、概述  

  今天和同事一起调代码,定位到一处很耗时的地方,在某个线程中,同步周期需要保证在2ms(如果耗时不到2ms,那么让剩下的时间进行sleep).

  但是在调用一个模块的内部函数时,时不时的就飘到了3~5ms,时间抖动毫无保证。后来仔细分析了一下被调用的函数,发现是在查找链表中某个目标节点时,由于目标节点的不确定行,导致耗时飘来飘去。

  后来想到是否可以用“哨兵”的思路来解决问题,于是就试了一下,果然有效。特分享于此,使用2段代码来看一下代码执行效率的提升。

2、普通的算法

  所谓哨兵,就是一个标志,一个与查找目标对象一样的操作对象。

  假如有1000000个纸箱,每个箱子里面有一个纸条,里面写有1~1000000这些数字,数字不会重复。现在别人给一个随机的数字,我们需要从这1000000个箱子里找到与这个数字相同的纸条,找到之后退出操作。

  分析:纸箱是无序的,所以我们需要从头遍历

(1)代码1

我们给一个500000的数字,要在这1000000个箱子中寻找纸条数字为500000

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>

#define LOOP_NUM 1000000

int main(void)
{
	long data[LOOP_NUM];
	long rand_num = 500000;
	struct timeval tv1, tv2;

	for (long i = 0;i < LOOP_NUM;i++)
	{
		data[i] = i;
	}

	gettimeofday(&tv1,0);
	for (long i= 0;i<LOOP_NUM;i++)
	{
		if (data[i] == rand_num)
		{
			printf("find the box %ld\n",data[i]);
			break;
		}
	}
	gettimeofday(&tv2, 0);
	long us1 = tv1.tv_sec * 1000000 + tv1.tv_usec;
	long us2 = tv2.tv_sec * 1000000 + tv2.tv_usec;

	printf("time elapse %ld\n",us2-us1);

	return 0;
}

 我们使用for循环遍历所有的箱子查找,我们可以看到查找花了2840us.

 (2)代码2(哨兵节点)

int main(void)
{
	long data[LOOP_NUM+1];
	long rand_num = 500000,i=0;
	struct timeval tv1, tv2;

	for (long i = 0;i < LOOP_NUM;i++)
	{
		data[i] = i;
	}
	data[LOOP_NUM] = 500000;  /*增加一个哨兵节点*/
	gettimeofday(&tv1,0);
	while(1)
	{
		if(data[i] == rand_num)
		{
			printf("find the box %ld\n",data[i]);
			if(i==LOOP_NUM)
			{
				printf("find the sentinal box\b");
			}
			break;
		}
		i++;
	}
	gettimeofday(&tv2, 0);
	long us1 = tv1.tv_sec * 1000000 + tv1.tv_usec;
	long us2 = tv2.tv_sec * 1000000 + tv2.tv_usec;

	printf("time elapse %ldus.\n",us2-us1);

	return 0;
} 

执行结果:

   使用哨兵后,很明显提高了代码执行效率,代码1中使用for循环中对于i的最大值每个循环都要进行比较判断,这就降低了代码的执行效率,代码2加入了哨兵节点,多一个纸箱,纸箱里面的纸条写成500000。如果一直查找到哨兵节点才退出循环,表示没有找到。代码2中我们使用while循环,没有了每次箱子最大数量的比较判断,这就增加了代码的执行效率。

 

 

 

 

 

posted @ 2022-06-06 10:17  轻轻的吻  阅读(194)  评论(0编辑  收藏  举报