排序算法总结

排序

有n个记录的序列为{R1,R2……Rn},其对应关键字为{K1,K2……Kn},需确定一种排列{P1,P2……Pn}使其关键字满足KP1<KP2<KP3……<KPn等关系。即使得序列成为一个按关键字有序的序列{Rp1,Rp2,……Rpn},这样的操作就称为排序
用人话说就是从大到小,要么从小到大排列就OK。

  • 排序的稳定性
    存在两个关键字相等Ki = Kj(i != j,i < j),如果从小到大排序后 Ri仍在Rj前面,则是稳定排序,反之,则是不稳定排序。

  • 内排序和外排序
    内排序就是待排序所有记录放置于内存中,外排序需要在内外存进行多次交换,我们多使用内排序。
    影响内排序的性能:时间性能,就是时间复杂度;辅助空间,就是空间复杂度;算法复杂性,是算法本身的复杂性

  • 排序分类
    按照算法复杂度排序算法可分为两类:

  1. 冒泡排序、简单选择排序、直接插入排序属于插入排序
  2. 希尔排序、堆排序、归并排序、快速排序属于改进算法。

    Read More

ubuntu更换清华源

何为源

sudo apt-get update这个命令我们常用来更新一下源列表,这里面就是一些网址信息,这个网址信息里面有各种软件什么的,非常正规安全的那种。

我们安装Ubuntu的时候,有一个默认的源列表,但是呢,这个源列表里面有很多都没有办法访问了,我不知道是不是国情问题。所以造成的问题就是我们经常要更新一些软件就失败……

国内企业、高校研究机构都都提供ubuntu的源列表。比较好用的是清华源、阿里源。

Read More

Markdown用法总结

  • Markdown是时下程序员圈子最火的文档格式,它的宗旨就是易写易读
  • 目前很多论坛、博客都支持Markdown,Github、Stack overflow等程序猿熟知的社区都支持Markdown。Markdown也兼容HTML,所以前端对这个几乎没有学习成本。而且我本人博客也是使用的Markdown格式,因此有必要把一些常用的Markdown语法做一个简要的介绍,技多不压身嘛。

  • 以下介绍常用的Markdown语法

  • 标题
  • 字体
  • 代码与代码块
  • 分割线
  • 列表
  • 图片&链接
  • 视频

Read More

目标跟踪算法--模板匹配

  • 目前目标跟踪在机器视觉领域发展较快,有很多跟踪方法,例如传统的模板匹配、camshift、meanshift等算法。最近在疯狂学习opencv中,所以从最简单的模板匹配实现开始。

  • 为了提高兴趣,做一个人脸检测与跟踪算法,检测部分算法见【人脸检测】。这里采用鼠标选取跟踪的目标,在利用模板匹配的方式进行目标跟踪。

    Read More

智能指针

普通指针在内存管理方面非常不方便,new和delete必须成对使用,非常容易出现错误。

智能指针模板类

定义了类似指针的对象,可以将new得到的内存地址赋给这些对象,当这些智能指针过期时,将自动调用其(智能指针对象)的析构函数,这些析构函数将使用delete来释放内存。
因此如果使用智能指针指向new的内存,无需手动释放这些内存,智能指针过期时,内存自动被释放。

Read More

友元、异常和其他相关问题

友元

友元类

友元函数用于类的扩展接口,类并非只能拥有友元函数,还能够将类作为友元类。友元类的所有方法都可以访问原始类的私有成员和保护成员。
以电视机和遥控器的关系,解释友元的作用以及相关问题

Read More

core组件进阶

  • LUT函数: LOOK UP TABLE 操作
    用于批量元素查找、扫描和操作图像。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //首先我们建立一个mat型用于查表
    Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.data;
    for( int i = 0; i < 256; ++ i)
    {
    p[i] = table[i];
    }
    //然后我们调用函数(I 是输入, J 是输出):
    for(int i = 0; i < times; ++ i)
    LUT(I, lookUpTable, J);
  • 计时函数
    ‘getTickCount()’函数: 返回CPU自某个时间以来走过的时钟周期;
    ‘getTickFrequency()’函数: 返回CPU一秒钟的时钟周期;
    故使用以上两个函数可以得到某段程度的运行时间:

    1
    2
    3
    4
    double time1 = static_cast<double>(getTickCount()); //记录起始时间
    // 你的程序...
    time1 = ((double)getTickCount() - time1) / getTickFrequency();
    cout << "程序运行时间 : " << time1 << endl;
  • 访问图中像素的方法
    图像处理最基本的就是处理每个点的像素啦,所以呢,如何访问每个像素点呢。

  1. 指针访问: C操作符[]
    如果是一幅 640 *320 的图像,就把他看成是一个二维数组 pic[640][320]。两个嵌套的for循环,即可完成图像像素点的遍历。

OpenCV数据结构与基本绘图

  1. IplImage与Mat
    在最开始,OpenCV使用基于C语言接口构建,因此在较早版本的OpenCV中使用IplImage存储图像数据。这就造成了一定的问题,在调试了的时候,需要程序员手动release为IplImage分配的内存,不然可能造成内存泄漏。
    在OpenCV2.0以来,就引入了C++接口,也就产生了基于C++的Mat数据结构,没错,它是可以自动内存管理的,因此我们现在用的最多的就是Mat数据结构了。Mat类很方便,不用手动分配内存、释放内存。
    那么为什么IplImage还继续顽强存在呢,那就是因为大部分嵌入式系统只支持C语言.

  2. Mat类 包含两个数据部分,一个部分是矩阵头(矩阵尺寸、存储方法、存储地址等),另一部分指向存储所有像素值得矩阵。

需要记住的是,大多时候复制Mat类,只是引用矩阵头,而不是复制整个像素矩阵,这将导致巨大的时间成本。因此,OpenCV采用引用计数机制,每个Mat对象都有独自的矩阵头,但是共享一个像素矩阵。常见的复制构造函数、赋值符号都是只复制矩阵头,而不是复制整个像素矩阵。

Read More

虚析构函数的作用

  • 为什么要使用虚析构函数?
    如果有这样两个类:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class person{
    person(...);
    virtual ~person();
    virtual void show(); //具体定义就不写了,反正和派生类不一样
    };
    class student : public person{
    virtual void show();
    };
    person temp_p(...);
    student temp_s(...);
    person * temp1 = temp_p;
    person * temp2 = temp_s;

为了发挥C++多态的特性,我们一般会使用虚函数,采用基类指针或者引用来 对基类对象或者派生类对象进行操作。但是这样会有一个问题,如果析构函数不是虚函数,那么基类指针temp2结束代码段时,就只会调用指针类型(就是基类)的析构函数。如果这个基类指针指向的是派生类对象,那么派生类的析构函数就不会被调用,显然是有一定问题隐患的。
因此,使用虚析构函数可以确保正确的析构函数序列被调用。

虚函数的工作原理

  • 为什么需要虚函数?
    在编写程序的过程中,一定会遇到这样的场景。派生类继承了基类的方法,但是我们希望同一个方法在派生类和基类中的行为不同,就是方法取决于调用的对象(这种复杂的行为就是多态)。实现多态的公有继承有两种重要的机制。
  1. 在派生类中重新定义基类方法 (可以定义不同方法)
  2. 虚函数 (可以使基类引用或指针可以调用派生类新定义的方法)
  • 虚函数基本语法?
    在需要重新定义的方法前添加关键字 virtual,然后分别定义即可。

    Read More