二進制-高效位運算

數獨

數獨是介紹位運算的好例子,運用位運算和不運用效率差別還是挺大的。我們先看數獨需求:

1、當前數字所在數字均含1-9,不重復

2、當前數字所在數字均含1-9,不重復

3、當前數字所在(即3x3的大格)數字均含1-9,不重復(宮,如下圖每個粗線內是一個宮)

常規算法

若是我們采用常規方式的,每填寫一個數字,需要檢查當前行、列,宮中其他位置是否有重復數字,極端情況下需要循環27(3*9)次來進行檢查,我們看下常規算法下check

	int check(int sp) { // 檢查同行、列、九宮格有沒有相同的數字,若有傳回 1 int fg= 0 ; if(!fg) fg= check1(sp, startH[sp], addH) ; // 檢查同列有沒有相同的數字 if(!fg) fg= check1(sp, startV[sp], addV) ; // 檢查同行有沒有相同的數字 if(!fg) fg= check1(sp, startB[sp], addB) ; // 檢查同九宮格有沒有相同的數字 return(fg) ; } int check1(int sp, int start, int *addnum) { // 檢查指定的行、列、九宮格有沒有相同的數字,若有傳回 1 int fg= 0, i, sp1 ; //萬惡的for循環 for(i=0; i<9; i++) { sp1= start+ addnum[i] ; if(sp!=sp1 && sudoku[sp]==sudoku[sp1]) fg++ ; } return(fg) ; }

這個效率是否很嚇人,每次填寫一個就需要check27次,有木有check一次的算法?當然有了,采用位運算,一次搞定。來我們看下位運算的思路:

位運算

我們看上圖所示,單個行(或者列、宮)數據,都是有1-9共9個數字,我們統稱為九宮數字。若是我們采用二進制,以九宮數字充當二進制數據的位坐標,采用9位的二進制就可以與之一一對應,位上有數據,標識為1,無數據標識為0,如此一個正數就能解決一行九宮數據狀態,無需需存一個數組

比如 看圖中深紅色部分,當前九宮數據中已經有1和3,那么二進制右起第一位和第三位標識為1,一個數字5就可以存下當前行(或者列、宮)數組狀態了,如若數字為511表明,所有的九宮數字都用完了,如圖第一行。

check一個數字是否已經被占用了,可以采取位運算來獲取二進制的右數第k位來查看是否是1,若是1,表明指定數字已經被占用了。我們看下具體check算法:

	// sp 是當前位置索引,indexV 行索引,indexH 列索引,indexB九宮格索引int check(int sp,int indexV,int indexH,int indexB) { // 檢查同行、列、九宮格沒有用到的數字,若已經用過返回 1 int status = statusV[indexV]|statusH[indexH]|statusB[indexB]; //9個數字都被用了 if (status>=STATUS_MAX_VALUE) { return 1; } int number=sudoku[sp]; //取右數第k位,若是1表明這個值已經存在了 return status>>(number-1)&1; } 
	// 行、列、宮二進制數據指定位置標記為1int markStatus(int indexV,int indexH,int indexB,int number){ if (number<1) { return 0; } //把右數第k(從1計數)位變成1 statusV[indexV]|=(1<<(number-1)); statusH[indexH]|=(1<<(number-1)); statusB[indexB]|=(1<<(number-1)); }

我們以以下圖例位置舉例,如何獲得當前位置可以填取的數字

可以看到2個位運算就解決了檢查可用數字的操作了,而之前常規算法,需要用27次查找才可以獲取到。當然了這個算法還可以優化,比如采用啟發式DFS,搜索可用數字,速度更快,感興趣可點擊這里。

常規算法和位運算算法C語言代碼,我已經上傳碼云了,想了解的點擊下面鏈接,自行去查看去。(常規算法google的)

地址:?常規算法數獨,位運算版本數獨

?基礎

位操作符

符號含義規則
&?兩個位都為1時,結果為1
|有一個位為1時,結果為1
^異或0和1異或0都不變,異或1則取反
~取反0和1全部取反
<<左移位全部左移若干位,高位丟棄,低位補0
>>算術右移位全部右移若干位,,高位補k個最高有效位的值
>>邏輯右移位全部右移若干位,高位補0

注意:

1、位運算只可運用于整數,對于float和double不行。

2、另外邏輯右移符號各種語言不太同,比如java是>>>。

3、位操作符的運算優先級比較低,盡量使用括號來確保運算順序。比如1&i+1,會先執行i+1再執行&。

?

應用實例

很棒的應用實例,你可以mark一下,方便以后對照使用。

1、混合體

位運算實例

位運算功能示例
x >> 1去掉最后一位101101->10110
x << 1在最后加一個0101101->1011010
x << 1 | 1在最后加一個1101101->1011011
x | 1把最后一位變成1101100->101101
x & -2把最后一位變成0101101->101100
x ^ 1最后一位取反101101->101100
x | (1 << (k-1))把右數第k位變成1101001->101101,k=3
x & ~ (1 << (k-1))把右數第k位變成0101101->101001,k=3
x ^(1 <<(k-1))右數第k位取反101001->101101,k=3
?x & 7取末三位1101101->101
x & (1 << k-1)取末k位1101101->1101,k=5
x >> (k-1) & 1取右數第k位1101101->1,k=4
x | ((1 << k)-1)把末k位變成1101001->101111,k=4
x ^ (1 << k-1)末k位取反101001->100110,k=4
x & (x+1)把右邊連續的1變成0100101111->100100000
x | (x+1)把右起第一個0變成1100101111->100111111
x | (x-1)把右邊連續的0變成111011000->11011111
(x ^ (x+1)) >> 1取右邊連續的1100101111->1111
x & -x去掉右起第一個1的左邊100101000->1000
x&0x7F取末7位100101000->101000
x& ~0x7F是否小于127001111111 &?~0x7F->0
x &?1判斷奇偶00000111&1->1

2、交換兩數

int swap(int a, int b) { if (a != b) { a ^= b; b ^= a; a ^= b; } } 

?

3、求絕對值

int abs(int a) { int i = a >> 31; return ((a ^ i) - i); } 

?

4、二分查找32位整數前導0個數

int nlz(unsigned x) { int n; if (x == 0) return(32); n = 1; if ((x >> 16) == 0) {n = n +16; x = x <<16;} if ((x >> 24) == 0) {n = n + 8; x = x << 8;} if ((x >> 28) == 0) {n = n + 4; x = x << 4;} if ((x >> 30) == 0) {n = n + 2; x = x << 2;} n = n - (x >> 31); return n; }

5、二進制逆序

int reverse_order(int n){ n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1); n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2); n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4); n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8); n = ((n & 0xFFFF0000) >> 16) | ((n & 0x0000FFFF) << 16); return n; }

6、?二進制中1的個數

 unsigned int BitCount_e(unsigned int value) { unsigned int count = 0; // 解釋下下面這句話代碼,這句話求得兩兩相加的結果,例如 11 01 00 10 // 11 01 00 10 = 01 01 00 00 + 10 00 00 10,即由奇數位和偶數位相加而成 // 記 value = 11 01 00 10,high_v = 01 01 00 00, low_v = 10 00 00 10 // 則 value = high_v + low_v,high_v 右移一位得 high_v_1, // 即 high_v_1 = high_v >> 1 = high_v / 2 // 此時 value 可以表示為 value = high_v_1 + high_v_1 + low_v, // 可見 我們需要 high_v + low_v 的和即等于 value - high_v_1 // 寫簡單點就是 value = value & 0x55555555 + (value >> 1) & 0x55555555; value = value - ((value >> 1) & 0x55555555); // 之后的就好理解了 value = (value & 0x33333333) + ((value >> 2) & 0x33333333); value = (value & 0x0f0f0f0f) + ((value >> 4) & 0x0f0f0f0f); value = (value & 0x00ff00ff) + ((value >> 4) & 0x00ff00ff); value = (value & 0x0000ffff) + ((value >> 8) & 0x0000ffff); return value; // 另一種寫法,原理一樣,原因在最后一種解法中有提到 //value = (value & 0x55555555) + (value >> 1) & 0x55555555; //value = (value & 0x33333333) + ((value >> 2) & 0x33333333); //value = (value & 0x0f0f0f0f) + ((value >> 4) & 0x0f0f0f0f); //value = value + (value >> 8); //value = value + (value >> 16); //return (value & 0x0000003f); }

?

轉載于:https://www.cnblogs.com/hwcs/p/7196918.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455711.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455711.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455711.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

pytorch resnet50_PyTorch終于能用上谷歌云TPU,推理性能提升4倍,我們該如何薅羊毛?...

曉查 發自 凹非寺量子位 報道 | 公眾號 QbitAIFacebook在PyTorch開發者大會上正式推出了PyTorch 1.3&#xff0c;并宣布了對谷歌云TPU的全面支持&#xff0c;而且還可以在Colab中調用云TPU。之前機器學習開發者雖然也能在Colab中使用PyTorch&#xff0c;但是支持云TPU還是第一次…

x264里的2pass指的是什么意思? x264源代碼分析2.encode()

A:x264里的2pass指的是什么意思?另外stat是什么意思, 比如有個參數--stats <string> Filename for 2 pass stats [/"%s/"]/n", defaults->rc.psz_stat_out );stats在這是什么意思? 2pass是2次編碼的意思&#xff0c;stats是統計文檔的名稱&a…

項目啟動居然如此重要!

項目的啟動階段比較短&#xff0c;項目經理往往容易忽視這個階段&#xff0c;但是&#xff0c;項目的啟動卻具有著重要的意義。 定基調&#xff1a; 基調包括工作的節奏、團隊氛圍和溝通風格等。 一首歌的第一句決定了這首歌的基調&#xff0c;如何唱好這第一句就是項目啟動所要…

mysql數據庫導入導出文件sql文件

window下 1.導出整個數據庫 mysqldump -u 用戶名 -p 數據庫名 > 導出的文件名 mysqldump -u dbuser -p dbname > dbname.sql 2.導出一個表 mysqldump -u 用戶名 -p 數據庫名 表名> 導出的文件名 mysqldump -u dbuser -p dbname users> dbname_users.sql 3.導出…

Android Studio主題設置、顏色背景配置

2019獨角獸企業重金招聘Python工程師標準>>> color-themes 效果展示 打開http://color-themes.com/有很多樣式可供選擇 1. Monokai Sublime Text 3(color theme) 2. Solarized Light (color theme) 3. Visual Studio 2015 Dark(color theme) 導入方式 下載主…

JavaScript中的函數

js函數 *第一種是使用function語句定義函數 function abc(){alert(abc); }*第二種是在表達式中定義函數 var 函數名 function\(參數1&#xff0c;參數2&#xff0c;…\){函數體};//例如&#xff1a;//定義var add function\(a,b\){return ab;}//調用函數document.write\(a…

x264源代碼分析1。fread()

相關說明:1. 使用版本: x264-cvs-2004-05-11 2. 這次的分析基本上已經將代碼中最難理解的部分做了闡釋,對代碼的主線也做了剖析,如果這個主線理解了,就容易設置幾個區間,進行分工閱讀,將各個區間擊破了. 3. 需要學習的知識:a) 編碼器的工作流程.b) H.264的碼流結構,像x264_sp…

在centos下安裝pycrypto報錯 RuntimeError: autoconf error

解決&#xff1a;yum -y install gcc File "/usr/lib64/python3.6/distutils/dist.py", line 974, in run_command cmd_obj.run() File "/usr/lib64/python3.6/distutils/command/build.py", line 135, in run self.run_command(cm…

Java多線程實現異步調用

在Java平臺,實現異步調用的角色有如下三個角色&#xff1a;調用者、 提貨單 、真實數據&#xff0c;一個調用者在調用耗時操作,不能立即返回數據時,先返回一個提貨單 .然后在過一斷時間后憑提貨單來獲取真正的數據.去蛋糕店買蛋糕&#xff0c;不需要等蛋糕做出來(假設現做要很長…

sql server 2008 r2卸載重裝_免費下載:Intouch軟件、Windows操作系統、SQL數據庫,VB6.0、C#...

為大家整理了常用的Windows操作系統和安裝軟件&#xff0c;基本上都是經過我們項目測試OK的版本&#xff0c;以后項目調試就齊全了&#xff0c;不用再“東奔西走”&#xff0c;“小鹿亂撞”了。整理不易&#xff0c;若對您有幫助請關注并轉發&#xff0c;以便幫助到更多的人。I…

Android ToolBar 使用完全解析

ToolBar簡介 ToolBar是Android 5.0推出的一個新的導航控件用于取代之前的ActionBar&#xff0c;由于其高度的可定制性、靈活性、具有Material Design風格等優點&#xff0c;越來越多的應用也用上了ToolBar&#xff0c;比如常用的知乎軟件其頂部導航欄正是使用ToolBar。官方考慮…

【零散積累】傳輸文件(sz/rz/scp命令)

來自wiki遷移頁面路徑&#xff1a;劉旺的主頁 / 個人零散積累 / 01> 傳輸文件&#xff08;sz/rz/scp命令&#xff09; 工作中的傳輸文件會出現在linux之間&#xff0c;或者linux與windows之間。 一、怎么實現linux與windows之間的文件傳輸&#xff1f; 1.sz和rz是什么 s…

x264_macroblock_cache_load()

功能:完成將已編碼數據參數和待編碼數據裝入到h->mb.cache中,下圖是BUF中存儲的數據在以MB為單位的時候的存儲順序 x264_macroblock_cache_load( h, i_mb_x, i_mb_y );//是把當前宏塊的up宏塊和left宏塊的intra4x4_pred_mode&#xff0c;non_zero_count加載進來&#xff0c…

U(優)盤安裝FreeBSD-9.0+GNOME_lite桌面

貼圖在我的主頁&#xff1a;http://hi.baidu.com/daodej/item/26313f4fc3db51ef1f19bcc6 修訂于&#xff1a;2012/07/04 標題&#xff1a;U(優)盤安裝FreeBSD-9.0GNOME_lite桌面&#xff0c;boot0啟動XP(Windows)、FreeBSD、Ubuntu(Linux)三系統 【黑括號表示說明&#xff0c;中…

【零散積累】 vim常用操作

類型 操作 含義 刪除 dd 刪除游標所在的一整行(常用) ndd n為數字。刪除光標所在的向下n行&#xff0c;例如20dd則是刪除光標所在的向下20行 d1G 刪除光標所在到第一行的所有數據 dG 刪除光標所在到最后一行的所有數據 d$ 刪除光標所在處&#xff0c;到該…

生活中常見物聯網實例_物聯網網關常見問題解答(一)

1.為什么物聯網解決方案需要網關&#xff1f;物聯網網關彌合了設備&#xff0c;傳感器&#xff0c;設備&#xff0c;系統和云之間的通信鴻溝。通過系統地連接云&#xff0c;物聯網網關提供了本地處理和存儲&#xff0c;并具有基于傳感器輸入的數據自主控制現場設備的功能。物聯…

predict_16x16[i_mode]( p_dst, i_stride )lowres

h->predict_16x16[i_mode]( p_dst, i_stride ); 計算對應預測模式時的預測采樣值。輸出放到dst指向的數組中。Pred0ct_16x16是7個元素指向的數組&#xff0c;數組的每個元素是一個指向函數的指針變量&#xff0c;在x264_predict_16x16_init函數初始這個指針數組。7個元素分…

【零散積累】shell腳本學習

來自wiki遷移頁面路徑&#xff1a;劉旺的主頁 / 個人零散積累 / 03> shell腳本學習 case Shell case語句&#xff08;多分支條件判斷&#xff09; $( ) Linux—shell中$(( ))、$( )、與${ }的區別 - chengd - 博客園 在bash中&#xff0c;$( )與 &#xff08;反引號&…

mysql 表鎖-解鎖

遇到問題“”用工具navicat打開一張表的時候&#xff0c;有的時候會發現這張表怎么打不開&#xff0c;關了navicat工具&#xff0c;再打開&#xff0c;也是同樣的狀態。查看表鎖&#xff1a;show OPEN TABLES where In_use > 0;查看是否是表鎖住了。-- 查看進程號 show proc…

alsa 測試 linux_Electron 構建步驟 (Linux)

遵循下面的引導&#xff0c;在 Linux 上構建 Electron .PrerequisitesPython 2.7.x. 一些發行版如 CentOS 仍然使用 Python 2.6.x &#xff0c;所以或許需要 check 你的 Python 版本&#xff0c;使用 python -V.Node.js v0.12.x. 有很多方法來安裝 Node. 可以從 Node.js下載原文…