成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

哨兵節點:思想簡單,效果很棒的編程算法

開發 后端
所謂的哨兵,就是一個標志,一個與查找目標對象一樣的操作對象。

別人的經驗,我們的階梯!

今天和同事一起調代碼,定位到一處很耗時的地方。

在某個線程中,同步周期需要保證在??2???毫秒(如果耗時不到??2???毫秒,那么就讓剩下的時間進行??sleep??)。

但是在調用一個模塊的內部函數時,時不時的就飄到了??3~5??毫秒,時間抖動毫無保證。

后來仔細分析了一下被調用的函數,發現是在查找鏈表中某個目標節點時,由于目標節點的不確定性,導致耗時飄來飄去。

后來想到是否可以用"哨兵"的思路來解決問題,于是就試了一下,果然有效。

特分享于此,使用??2??段代碼來看一下代碼執行效率的提升。

普通的算法

所謂的哨兵,就是一個標志,一個與查找目標對象一樣的操作對象。

以前有一本書中舉過這樣的一個例子:

假如有??10000???個紙箱,每個箱子里面都有一張紙條,紙條上寫有??1 ~ 10000??這些數字,數字不會重復。

現在:別人給了一個隨機的數字,我們需要在這??10000??個箱子里找到與這個數字相同的紙條,找到之后退出操作。

面對這個問題,最直覺的想法就是:從頭開始,遍歷這??10000??個箱子,檢查其中的紙條上數字是否與目標相同。

因為紙箱里的紙條不是按照順序排列的,所以只能從頭開始遍歷;

大概就是下面這個樣子:

int lookfor_num = xxx;
for (int i = 0; i < 10000; ++i)
{
if (box[i] == lookfor_num)
{
printf("找到了!箱子編號是:%d \n", i);
break;
}
}

從上面這段示意性代碼中可以看出,在??for???循環中主要有??2??個比較指令:

  1. 比較箱子的編號 i 是否到了最后一個箱子;
  2. 比較箱子里的紙條上數字,是否與要查找的目標數字相同;

為了便于量化問題,我們寫一個測試代碼,打印出??for??循環的時間消耗。

為了便于客觀比較,在測試代碼中:

  1. 循環次數設置為 500000 萬次;
  2. 箱子里紙條上的數字按順序存放,不影響討論問題的本質;
  3. 查找的數字設置為一個中間值 500000;

測試文件:??loop1.c??。

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#define LOOP_NUM 1000000
int main(int argc, char *argv[])
{
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("hit rand_num. i = %ld \n", 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;
}

編譯:??gcc loop1.c -o loop1??。

執行:

圖片

耗時大概在??1350 ~ 1380??微秒左右。

哨兵算法

哨兵算法的主要思想就是:降低在??for??循環中的比較操作。

因為紙箱的數量是有限的,上面的代碼中,在還沒有找到目標數字之前,需要對紙箱的序號進行檢查:以免超過了最大的紙箱。

我們可以在最后額外添加一個紙箱,并且在其中存放我們查找的目標數字,額外添加的這個紙箱就叫做??哨兵??!

這樣的話,在??for??循環中,就不需要檢查當前這個紙箱序號是否超過了最大的紙箱。

因為:我們在哨兵紙箱中放了被查找的那個數字,所以是一定能夠找到目標數字的:

要么是在前面的紙箱中, 要么是在哨兵紙箱中!

因此,在??for??循環中,就只需要比較紙條上的數字,而不用比較紙箱的序號是否達到最后一個了。

當找到目標數字之后,唯一要多做的步驟是:檢查這個箱子是否為哨兵紙箱。

如果是哨兵紙箱:說明前面的紙箱中沒有查找到目標數字。

如果不是哨兵紙箱:說明在前面的紙箱中查找到了目標數字。

測試代碼??loop2.c??:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#define LOOP_NUM 1000000
int main(int argc, char *argv[])
{
long data[LOOP_NUM + 1]; // add another room
long rand_num = 500000;
struct timeval tv1, tv2;

for (long i = 0; i < LOOP_NUM; ++i)
{
data[i] = i;
}
data[LOOP_NUM] = rand_num; // add a sentinel

gettimeofday(&tv1, 0);
long i = 0;
while (1)
{
if (data[i] == rand_num)
{
if (i != LOOP_NUM)
{
printf("hit rand_num. i = %ld \n", i);
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: %ld \n", us2 - us1);
return 0;
}

編譯:??gcc loop2.c -o loop2??。

執行:

圖片

耗時大概在??960 ~ 990??微秒之間。

小結

這篇短文僅僅是用??for??循環來討論哨兵的編程思想。

在其它的一些編程場景中,應用的機會還是挺多的,也能夠非常顯著的提升代碼的執行效率。

責任編輯:姜華 來源: IOT物聯網小鎮
相關推薦

2009-06-15 10:25:46

Java編程思想Java

2013-12-19 10:16:17

算法思想

2013-06-17 11:21:27

2012-05-10 10:36:53

jQuery

2015-07-03 11:20:41

編程學習方法

2010-08-03 08:54:07

JDK 7Lambda表達式函數式編程

2010-07-26 08:35:06

ScalaJava

2012-08-22 08:58:39

編程

2009-07-17 17:25:31

敏捷開發

2009-07-03 11:27:11

JSP編程思想

2013-09-22 10:15:05

編程思想

2010-01-19 15:36:02

C++語言

2011-10-19 15:47:13

2022-05-12 09:00:50

動態規劃算法項目

2024-11-22 08:00:00

編程語言軟件開發

2020-12-14 06:43:02

并發編程JDK

2019-02-11 08:32:22

編程語言Go

2021-11-28 18:07:44

PythonRuby編程

2011-11-23 09:21:43

jQuery

2009-06-22 13:48:00

Java編程思想面向對象
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美一区二区三区在线看 | 欧美一二区 | 国产精品2| 亚洲综合色视频在线观看 | 大吊一区二区 | 欧美精品二区 | 亚洲一区av在线 | 欧美日韩精品一区二区天天拍 | 狠狠做六月爱婷婷综合aⅴ 国产精品视频网 | 永久免费av | 日韩在线视频网址 | av一二三区| 国产精品高清在线 | 国产一区二区电影 | 成人精品视频在线观看 | 成人h视频 | 国产精品一二三区 | 男人天堂999 | 中文字幕四虎 | 999久久精品| dy天堂 | 99精品国产成人一区二区 | 亚洲成人精品一区二区 | 国产在视频一区二区三区吞精 | 久久久国产一区 | 国产视频一区二区 | 亚洲精品在线免费看 | 久艹av | 日韩免费视频 | 一级看片免费视频囗交动图 | 欧美精品综合在线 | 久久久一区二区 | 久久久久国产一区二区三区四区 | 亚洲一二视频 | 国产中文 | 天啪| 亚洲视频免费一区 | 久久网亚洲 | www.av在线 | 91黄在线观看 | 日韩成人国产 |