QT Demo 之 threading(3) triangle

同《QT Demo 之 threading(2) Spinner》一样,这一章也是把《QT
Demo 之 threading
》中的一个和threading完全独立的部分拿出来分析一下。

在中的WorkerScript.onMessage函数中有如下的调用,用来计算给定row和column下计算triangle的值:

    WorkerScript.onMessage = function(message) {
        //Calculate result (may take a while, using a naive algorithm)
        var calculatedResult = triangle(message.row, message.column);
        //Send result back to main thread
        WorkerScript.sendMessage( { row: message.row,
                                    column: message.column,
                                    result: calculatedResult} );
    }

triangle的意义是三角形,但是我们通过程序的运算结果知道在这里它实际表达的是求排列组合中的组合数。

排列组合简述

而排列组合的定义(来自百度百科)如下:

排列组合是组合学最基本的概念。所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序。组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。

其中组合的计算公式如下:

原有算法

示例中的实现代码如下:

function triangle(row, column) {
    if (cache[row][column])
        return cache[row][column]
    if (column < 0 || column > row)
        return -1;
    if (column == 0 || column == row)
        return 1;
    return triangle(row-1, column-1) + triangle(row-1, column);
}

这种计算方法的原理是采用了下述的公式:

即:triangle(row-1, column-1) + triangle(row-1, column) = triangle(row, column)

这种计算方法本身没有问题,但是由于其采用加法进行递归处理,而且是一变二的递归调用,那么这个调用次数就非常可观了。

经过测试,从triangle(63,1)到triangle(63,5),triangle函数每次的递归调用次数和花费时间如下:

  (63,1) (63,2) (63,3) (63,4) (63,5)
调用次数 125 3905 79421 1191329 14057693
运行时间(ms) 1 15 346 4492 52352

可以看出这种运算方法的效率是何其底下,可能原作者在这里是为了演示后台线程的长时间运行不会阻塞UI线程的效果。但是我不得不吐槽的是,在这里使用一个纯粹的sleep也比这种很低效的运算方法强啊。

吐槽2:作者在开始定义了一个64*64的二维数组,但是,在代码中完全没有使用到啊!!!真是做到了既浪费空间又不提高时间效率!

改进算法

通过上面我们提到的组合计算公式,我们可以推导出下面的公式:

按照上面的公式,我们对triangle函数进行了优化:

function triangle(row, column) {
    if (cache[row][column])
        return cache[row][column]
    if (column < 0 || column > row)
        return -1;
    if (column == 0 || column == row)
        return 1;
    return triangle(row, column-1) / column * (row+1-column);
}

此处仍然是采用了递归的方法,故边界条件和递归终止条件都没有变,只是修改了每次递归的算法。

经过测试,从triangle(63,1)到triangle(63,5),triangle函数每次的递归调用次数和花费时间如下:

  (63,1) (63,2) (63,3) (63,4) (63,5)
调用次数 1 2 3 4 5
运行时间(ms) 0 0 0 0 0

和上面的算法结果一比较就知道原有算法是何其的效率低下。

总结

这一节从Qt方面来讲没有学习新知识,但是通过分析和优化triangle函数的实现,我们了解到如何通过在算法上进行优化从而极大的提高应用的计算效率和显示效果。

在进行软件开发中,做对只是最最基本的一步,做好才是最优价值的。

时间: 2024-10-06 16:43:07

QT Demo 之 threading(3) triangle的相关文章

QT Demo 之 threading(2) Spinner

在QT Demo 之 threading一章中我们使用到了Spinner,但是由于Spinner本身和thread部分关系不大,而是作为一个独立的自定义组件,因此我们在这一章中单独讲解. Spinner定义在threading/workerscript/Spinner.qml文件中,由一个Text和Rectangle组成: Rectangle { width: 64 height: 64 property alias value: list.currentIndex property alias

QT Demo 之 threading

在学习了MouseArea.Text.Image这些基本组件后,我们这一章学习如何在QML中完成一些异步处理. 这一章我们通过下述两个例子来分别讲解一下Timer和WorkerScript的使用. threadedlistmodel/timedisplay.qml 这一个示例的原始代码中同时使用了Timer和WorkerScript来完成一个比较简单的工作,为了简化处理,我针对代码做了一些小改动,去掉了WorkerScript部分(同时包括dataloader.js部分),只使用Timer来完成

QT Demo 之 window(3) Qt.quit()

在上一章<QT Demo 之 window(2) Splash>学习中留下一个TODO没有解决,就是在示例代码中有这样的一段: MouseArea { anchors.fill: parent onClicked: Qt.quit() } 其本意就是在显示Splash Screen的时候,如果点击Splash Screen图片就会退出整个程序,但实际结果就是报了一行错误: Signal QQmlEngine::quit() emitted, but no receivers connected

QT Demo 之 window(2) Splash

在QT Demo 之 window一章我们学习了在C++层的QQuickWindow的一些知识,这一章我们重点看一下源码中的Splash.qml文件,该文件给我们演示了如何使用splash screen来显示应用的启动及界面. 关于应用的启动界面,有一个最直观也是比较常见的例子就是photoshop,下图就是PS启动时显示的界面: 在这个例子里也是先显示一个Qt的Logo,然后再进入到主应用窗口中. 源码结构 Splash.qml实现了一个自定义的window来完成Splash screen的功

QT Demo 之 imageelements

在学习了MouseArea和Text之后,这一节开始学习image相关的知识. 和上一节QT Demo 之 text一样,imageelements的入口也是一个LauncherList,然后添加了5个子example,下面我就针对每一个子example进行详细分析. borderimage.qml 首先看到的是borderimage.qml的主体结构是由一个BorderImageSelector和Flickable组成的: Rectangle { id: page width: 320 hei

QT Demo 之 calqlatr(2) calqlatr.qml

import QtQuick 2.0 import "content" import "content/calculator.js" as CalcEngine 同样,这次我们针对qml代码开始的最常见的import部分也不放过了,也要至少做到基本了解和使用. 在Qml中如果需要使用系统组件,必须在开始进行声明.对于自定义的组件也需要在开始的时候import进来,并且需要注意的是,系统组件直接通过名称即可,而对于自定义组件,需要使用""包起来.

qt demo pro

qt demo pro qtdemo.pri TEMPLATE = app QT_VER = $$[QT_VERSION] QT_PATH = $$[QT_INSTALL_PREFIX] #message(Qt version is $$QT_VER) #message(Qt install prefix is $$QT_PATH) QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += debug_and

Qt5官方demo解析集32——Qt Quick Examples - Threading

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集31--StocQt 因为涉及到QML线程看到这个例子,发现它是属于Qt Quick Example这个系列的.这个系列共有19个demo,涵盖了Qt Quick中多种元素,有空我们把这个系列一篇篇做下来,相信是一趟不错的旅途~ 好了,在我们编写应用程序,尤其是用户界面程序,多线程往往是避不开的一个话题.界面卡死超过3秒,

QT Demo 之 calqlatr(1) main.cpp

其实从最开始要学习和分析Qt的Demo时选定的就是calqlatr工程,但是打开源码一看,貌似难度高了点,这才有了上面的几篇基本控件的分析.从这一章开始,我要拿下calqlatr这个Demo项目了. main.cpp main.cpp中的代码非常简单: #include "../../shared/shared.h" DECLARATIVE_EXAMPLE_MAIN(demos/calqlatr/calqlatr) DECLARATIVE_EXAMPLE_MAIN(NAME)是一个函数