成人免费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

編程思想

2022-05-12 09:00:50

動態規劃算法項目

2010-01-19 15:36:02

C++語言

2011-10-19 15:47:13

2024-11-22 08:00:00

編程語言軟件開發

2021-11-28 18:07:44

PythonRuby編程

2019-02-11 08:32:22

編程語言Go

2020-12-14 06:43:02

并發編程JDK

2011-11-23 09:21:43

jQuery

2009-06-22 13:48:00

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

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品免费视频大全最热 | 日日艹夜夜艹 | 国产高清视频一区二区 | 亚洲精品乱码久久久久久黑人 | 成人1区2区 | 2018中文字幕第一页 | 超碰电影 | 日本午夜在线视频 | 国产一区二区在线看 | 青娱乐av | 成人h动漫亚洲一区二区 | 91豆花视频 | 日本成人久久 | 狠狠干天天干 | 波多野结衣在线观看一区二区三区 | 日韩免费一区二区 | 羞羞的视频在线看 | 亚洲一区二区三区免费在线观看 | 国产一级在线观看 | 久久国产精品视频免费看 | 久艹网站| 久久精品视频91 | 91人人在线 | 欧美日韩专区 | 一级做a爰片性色毛片 | 精品国产一区二区三区性色av | 国产在线一区二区三区 | 99精品免费久久久久久日本 | 国产高清久久久 | 久久国产成人午夜av影院武则天 | 欧美日韩一区二区三区视频 | 日韩高清中文字幕 | 久久久国产一区二区 | 999久久久 | 日韩综合色| 久久成人精品视频 | 亚洲日韩中文字幕一区 | 久干网| 精品乱码一区二区三四区 | 国内精品免费久久久久软件老师 | 日韩在线中文 |