Delphi下实现全屏快速找图找色 二、矩阵遍历
二、矩陣遍歷
矩陣遍歷是一個(gè)數(shù)據(jù)結(jié)構(gòu)方面的問題。假設(shè)有一個(gè)矩陣Matrix,它共有RowCount行,每行有ColCount列,當(dāng)利用y表示行數(shù),x表示列數(shù),那么利用Matrix[y,x]就可以訪問矩陣中的任意元素。假設(shè)有一個(gè)10×10大小的矩陣,它的遍歷方法有以下三種:
此主題相關(guān)圖片如下:
(圖1)
?
在上圖中矩陣中的數(shù)字表示遍歷到元素的先后次序,箭頭表示遍歷的方向。第一種的一般遍歷法在很多編程書上都有介紹,而且經(jīng)常作為循環(huán)代碼的示范程序使用。這種遍歷方法稍加修改就可以做到從右上角開始、從左下角開始、從右下角開始。這種遍歷方法很簡(jiǎn)單,這里就不多說了。與一般遍歷相反,螺旋遍歷在所有的編程書和數(shù)據(jù)結(jié)構(gòu)書上都沒有講到。現(xiàn)在詳細(xì)的說明一下螺旋遍歷。
?
螺旋遍歷可以做到以一個(gè)基點(diǎn)為中心向四周遍歷,這個(gè)基點(diǎn)可以不是矩陣的中心點(diǎn),實(shí)際上基點(diǎn)可以是矩陣上的任意一點(diǎn),甚至可以是矩陣外的點(diǎn)。注意:這里所說的“點(diǎn)”是指可以用(y,x)訪問的元素,當(dāng)(y,x)坐標(biāo)超出矩陣范圍,例如(-1,-1),這就是矩陣外的點(diǎn)。可以看出螺旋遍歷對(duì)于找圖找色非常有用。螺旋遍歷實(shí)現(xiàn)起來并不難,仔細(xì)觀察圖1中的螺旋遍歷就會(huì)發(fā)現(xiàn)遍歷可以由遍歷方向和遍歷步數(shù)組成。從(3,2)點(diǎn)開始向上遍歷一步,再向右遍歷一步,再向下遍歷二步,再向左遍歷二步,這時(shí)完成一輪,遍歷方向又開始向上、向右、向下、向左一輪又一輪,同時(shí)遍歷步數(shù)逐步加大。當(dāng)向上遍歷時(shí)y總是減1;當(dāng)向右遍歷時(shí)x總是加1;當(dāng)向下遍歷時(shí)y總是加1;當(dāng)向左遍歷時(shí)x總是減1,這樣可以根據(jù)遍歷方向計(jì)算出坐標(biāo)的變化。另外螺旋遍歷有可能會(huì)訪問到矩陣外的點(diǎn),在訪問時(shí)要進(jìn)行判斷。正是由于螺旋遍歷會(huì)訪問矩陣外的點(diǎn),遍歷循環(huán)將無法停止從而出現(xiàn)死循環(huán)。這時(shí)要設(shè)定一個(gè)訪問計(jì)數(shù)VisitCount,當(dāng)遍歷循環(huán)訪問了矩陣中的所有點(diǎn)后退出循環(huán)。綜上所述,螺旋遍歷的示范代碼如下:
type
????//遍歷方向
????TAspect?=?(asLeft,?asRight,?asUp,?asDown);
const
????//移動(dòng)坐標(biāo)差
????MoveVal?:?array?[asLeft..asDown]?of?TPoint?=?(
????????(X?:?-1;?Y?:??0),?//asLeft
????????(X?:??1;?Y?:??0),?//asRight
????????(X?:??0;?Y?:?-1),?//asUp
????????(X?:??0;?Y?:??1)??//asDown
????);
????//矩陣大小
????RowCount?=?10;
????ColCount?=?10;
var
????//矩陣
????Matrix?:?array?[0..RowCount-1,0..ColCount-1]?of?Integer;
//螺旋遍歷(不支持步長(zhǎng))
procedure?MatrixOrder1_(y,x?:?Integer);
var
????Aspect?:?TAspect;
????VisitCount,Count,i?:?Integer;
begin
????VisitCount:=0;
????Aspect:=asUp;
????Count:=1;
????while?VisitCount<(RowCount*ColCount)?do
????begin
????????for?i:=0?to?Count-1?do
????????begin
????????????if?(x>=0)?and?(x<ColCount)?and
???????????????(y>=0)?and?(y<RowCount)?then
????????????begin
????????????????//訪問矩陣元素
????????????????Matrix[y,x]:=VisitCount;
????????????????VisitCount:=VisitCount+1;
????????????end;
????????????x:=x+MoveVal[Aspect].X;
????????????y:=y+MoveVal[Aspect].Y;
????????end;
????????case?Aspect?of
????????????asLeft??:?begin?Aspect:=asUp;???Count:=Count+1;?end;
????????????asRight?:?begin?Aspect:=asDown;?Count:=Count+1;?end;
????????????asUp????:?begin?Aspect:=asRight;?end;
????????????asDown??:?begin?Aspect:=asLeft;??end;
????????end;
????end;
end;
這里還有一個(gè)步長(zhǎng)的問題,所謂步長(zhǎng)就是指在遍歷的時(shí)候跳過一些點(diǎn),只平均訪問矩陣中的某些點(diǎn)。例如以下數(shù)據(jù)就是步長(zhǎng)為2以(3,2)為基點(diǎn)的螺旋遍歷后的矩陣,其中“-”表示遍歷時(shí)沒有訪問到的點(diǎn)。
輸出矩陣:
???+??0??1??2??3??4??5??6??7??8??9
?0?:??-??-??-??-??-??-??-??-??-??-
?1?:??8??-??1??-??2??-??9??-?16??-
?2?:??-??-??-??-??-??-??-??-??-??-
?3?:??7??-??0??-??3??-?10??-?17??-
?4?:??-??-??-??-??-??-??-??-??-??-
?5?:??6??-??5??-??4??-?11??-?18??-
?6?:??-??-??-??-??-??-??-??-??-??-
?7?:?15??-?14??-?13??-?12??-?19??-
?8?:??-??-??-??-??-??-??-??-??-??-
?9?:?24??-?23??-?22??-?21??-?20??-
使用步長(zhǎng)可以實(shí)現(xiàn)矩陣的抽樣查找,但上面給出的螺旋遍歷算法卻不支持步長(zhǎng)。因?yàn)樗迷L問計(jì)數(shù)退出循環(huán),使用步長(zhǎng)時(shí)會(huì)使矩陣中訪問到的點(diǎn)的數(shù)目不確定,使的上述算法出現(xiàn)死循環(huán)。對(duì)上述算法的一個(gè)改進(jìn)是使用一個(gè)邏輯變量記錄遍歷一輪是否有訪問到點(diǎn)。如果沒有,說明這一輪訪問已經(jīng)以位于矩陣之外可以退出循環(huán)。當(dāng)步長(zhǎng)為1時(shí)這種改進(jìn)的算法要比前面的算法更慢,因?yàn)樗翱辙D(zhuǎn)”一輪。而且這種算法也不支持矩陣外的點(diǎn)作為基點(diǎn),它會(huì)使循環(huán)提前退出。支持步長(zhǎng)的螺旋遍歷算法的示范代碼如下:注意這時(shí)的VisitCount僅作為測(cè)試使用,不作為退出循環(huán)的條件。
type
????//遍歷方向
????TAspect?=?(asLeft,?asRight,?asUp,?asDown);
const
????//遍歷步長(zhǎng)
????Interval?=?2;
????//移動(dòng)坐標(biāo)差
????MoveVal?:?array?[asLeft..asDown]?of?TPoint?=?(
????????(X?:?-Interval;?Y?:?0),?//asLeft
????????(X?:??Interval;?Y?:?0),?//asRight
????????(X?:?0;?Y?:?-Interval),?//asUp
????????(X?:?0;?Y?:??Interval)??//asDown
????);
????//矩陣大小
????RowCount?=?10;
????ColCount?=?10;
var
????//矩陣
????Matrix?:?array?[0..RowCount-1,0..ColCount-1]?of?Integer;
//螺旋遍歷2(支持步長(zhǎng))
procedure?MatrixOrder2(y,x?:?Integer);
var
????Aspect?:?TAspect;
????VisitCount?:?Integer;?//訪問計(jì)數(shù),測(cè)試用
????Count,i?:?Integer;
????Visit?:?Boolean;
begin
????VisitCount:=0;?//訪問計(jì)數(shù),測(cè)試用
????Visit:=false;
????Aspect:=asUp;
????Count:=1;
????while?true?do
????begin
????????for?i:=0?to?Count-1?do
????????begin
????????????if?(x>=0)?and?(x<ColCount)?and
???????????????(y>=0)?and?(y<RowCount)?then
????????????begin
????????????????//訪問矩陣元素
????????????????Matrix[y,x]:=VisitCount;
????????????????VisitCount:=VisitCount+1;?//訪問計(jì)數(shù),測(cè)試用
????????????????Visit:=true;
????????????end;
????????????x:=x+MoveVal[Aspect].X;
????????????y:=y+MoveVal[Aspect].Y;
????????end;
????????case?Aspect?of
????????????asLeft?:?begin
????????????????if?not?Visit?then?break;
????????????????Visit:=false;
????????????????Aspect:=asUp;
????????????????Count:=Count+1;
????????????end;
????????????asRight?:?begin?Aspect:=asDown;?Count:=Count+1;?end;
????????????asUp????:?begin?Aspect:=asRight;?end;
????????????asDown??:?begin?Aspect:=asLeft;??end;
????????end;
????end;
end;
?
對(duì)于回形遍歷與螺旋遍歷大同小異,這里就不多說了。在下面的壓縮包中是矩陣遍歷的示范程序,里面有一般遍歷、螺旋遍歷和回形遍歷的示范代碼,可以用于參考。
轉(zhuǎn)載于:https://www.cnblogs.com/MaxWoods/archive/2013/06/14/3135360.html
總結(jié)
以上是生活随笔為你收集整理的Delphi下实现全屏快速找图找色 二、矩阵遍历的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 驱动精灵离线版怎么安装和使用?
- 下一篇: ESP8266—“ICACHE_FLAS