android 算法可視化(1) --冒泡排序可視化實(shí)現(xiàn)

前言

以前寫了很多算法相關(guān)的博客诸蚕,每篇博客都會用word或者processing畫上很多圖,非常浪費(fèi)時(shí)間,那時(shí)候就一直有考慮能不能使用程序來實(shí)現(xiàn)這種過程,不僅不用自己畫那么圖垛叨,而且編程實(shí)現(xiàn)可視化的話,還可以動態(tài)更清晰的表現(xiàn)算法的過程钢悲。于是查找了相關(guān)的資料和自己對算法的理解先實(shí)現(xiàn)一個(gè)冒泡排序的可視化点额,代碼是Android的。

效果

bubble.gif

實(shí)現(xiàn)

要實(shí)現(xiàn)這個(gè)動畫效果莺琳,實(shí)際上需要兩個(gè)基本的模塊組成:一個(gè)BubbleView用于繪制,一個(gè)control控制器载慈,用于控制BubbleView的繪制惭等。


在這里插入圖片描述

1、BubbleView的實(shí)現(xiàn)
要實(shí)現(xiàn)上面的動畫要定義一個(gè)自己的BubbleView繼承View然后重寫View的onDraw()方法办铡,這個(gè)view要包含以下三個(gè)部分:

  1. 每一個(gè)數(shù)組元素的繪制
  2. 遍歷數(shù)組中當(dāng)前元素時(shí)的繪制
  3. 交換時(shí)的繪制

BubbleView中onDraw()方法中具體流程如下:


在這里插入圖片描述

1辞做、每一個(gè)數(shù)組元素的繪制

public class SortingVisualizer extends View {

    Paint paint;
    Paint textPaint;
    int[] array;
    int lineStrokeWidth = getDimensionInPixel(10);

    public SortingVisualizer(Context context) {
        super(context);
        initialise();
    }

    public SortingVisualizer(Context context, AttributeSet atrrs) {
        super(context, atrrs);
        initialise();
    }

    private void initialise() {
        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(lineStrokeWidth);
        textPaint = new TextPaint();
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(getDimensionInPixelFromSP(15));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (array != null) {
            int numberOfLines = array.length;
            float margin = (getWidth() - (30 * numberOfLines)) / (numberOfLines + 1);
            float xPos = margin + getDimensionInPixel(10);
            for (int i = 0; i < array.length; i++) {
                    canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), paint);
                canvas.drawText(String.valueOf(array[i]), xPos - lineStrokeWidth / 3, getHeight() - (float) ((array[i] / 10.0) * getHeight()) - 30, textPaint);
                xPos += margin + 30;
        }
    public void setData(int[] integers) {
        this.array = integers;
        invalidate();
    }

上面定義了兩個(gè)畫筆Paint,一個(gè)用于繪制元素的柱體寡具,

canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), paint);
xPos += margin + 30;

一個(gè)用于繪制柱體上面的text

canvas.drawText(String.valueOf(array[i]), xPos - lineStrokeWidth / 3, getHeight() - (float) ((array[i] / 10.0) * getHeight()) - 30, textPaint);

2秤茅、 遍歷數(shù)組中當(dāng)前元素時(shí)的繪制


    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (array != null) {
            int numberOfLines = array.length;

            float margin = (getWidth() - (30 * numberOfLines)) / (numberOfLines + 1);

            float xPos = margin + getDimensionInPixel(10);
            for (int i = 0; i < array.length; i++) {
                if (i == highlightPosition) {
                    canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), highlightPaintTrace);
//                   
                } 
                xPos += margin + 30;
            }
        }
    }

highlightPosition是外部排序時(shí)設(shè)置的值

3、交換時(shí)的繪制

  protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (array != null) {
            int numberOfLines = array.length;

            float margin = (getWidth() - (30 * numberOfLines)) / (numberOfLines + 1);

            float xPos = margin + getDimensionInPixel(10);
            for (int i = 0; i < array.length; i++) {
                if (i == highlightPositionOne) {
                    canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), highlightPaintSwap);
                } 
            highlightPositionOne = -1;
            highlightPositionTwo = -1;
        }


    }

control實(shí)現(xiàn)

control里面包括了冒泡排序算法童叠,和控制BubbleView重繪框喳,以及繪制的間隔等功能课幕,

   private void sort() {
        for (int i = 0; i < array.length; i++) {
            boolean swapped = false;
            for (int j = 0; j < array.length - 1 - i; j++) {
                highlightTrace(j);
                sleep();
                if (array[j] > array[j + 1]) {
                    highlightSwap(j, j + 1);
                    addLog("Swapping " + array[j] + " and " + array[j + 1]);
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    swapped = true;
                    sleep();
                }
            }
            if (!swapped) {
                break;
            }
            sleep();
        }
    }
    public void highlightSwap(final int one, final int two) {
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                bubbleView.highlightSwap(one, two);
            }
        });
    }

    public void highlightTrace(final int position) {
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                bubbleView.highlightTrace(position);
            }
        });
    }

冒泡排序算法

        for (int i = 0; i < array.length; i++) {
            boolean swapped = false;
            for (int j = 0; j < array.length - 1 - i; j++) {                
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    swapped = true;
                }
            }
            if (!swapped) {
                break;
            }
        }

參考

1、https://developer.android.com/reference/android/graphics/Canvas

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末五垮,一起剝皮案震驚了整個(gè)濱河市乍惊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌放仗,老刑警劉巖润绎,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诞挨,居然都是意外死亡莉撇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門惶傻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棍郎,“玉大人,你說我怎么就攤上這事达罗“映牛” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵粮揉,是天一觀的道長巡李。 經(jīng)常有香客問我,道長扶认,這世上最難降的妖魔是什么侨拦? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮辐宾,結(jié)果婚禮上狱从,老公的妹妹穿的比我還像新娘。我一直安慰自己叠纹,他們只是感情好季研,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著誉察,像睡著了一般与涡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上持偏,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天驼卖,我揣著相機(jī)與錄音,去河邊找鬼鸿秆。 笑死酌畜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卿叽。 我是一名探鬼主播桥胞,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼恳守,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了埠戳?” 一聲冷哼從身側(cè)響起井誉,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎整胃,沒想到半個(gè)月后颗圣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屁使,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年在岂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛮寂。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔽午,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酬蹋,到底是詐尸還是另有隱情及老,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布范抓,位于F島的核電站骄恶,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏匕垫。R本人自食惡果不足惜僧鲁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望象泵。 院中可真熱鬧寞秃,春花似錦、人聲如沸偶惠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忽孽。三九已至堂淡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扒腕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工萤悴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘾腰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓覆履,卻偏偏與公主長得像蹋盆,于是被迫代替她去往敵國和親费薄。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容