NgAgo - 不定期发布研究的东西

1.设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。

代码如下

void Del_X_3(LinkList &L,ElemType x)  
{  
    LNode *p;  //p指向待删除结点,

    if(L==NULL) //递归出口   
        return ;  
    if(L->data==x)  
    {  
        p=L;  
        L=L->next; //删除L,并让L指向下一结点 
        free(p);  
        Del_X_3(L,x); 
  
    }else   
    {  
        Del_X_3(L->next,x);//递归调用 
    }  
}  

这个解法肯定很多人觉得会断链,实际上由于算法第一个参数是一个引用,所以其中L=L->next至少是会表达L->next=L->next-next,这个L->next是最近的一个data非x的元素的一个指针。如果表达是L=L->next则说明:从头到目前所有的结点的data都等于x,并且全部都被删除了。

回首过去展望未来

2020年总结

首先祝各位新年快乐,站在2021年的元旦回首过去的一年,我们经历了大疫情,世界发生了前所未有的变化,习总书记提出了百年未有之大变局,这一年我们充满着感动,充满着信心走过了疫情,咱们中国老百姓为世界做了榜样,在这里由衷的感谢医护工作者们,你们辛苦了,也感谢国家能及时对抗疫情,号召全国支援武汉,一方有难八方支援是中国的好传统,应当继续发扬,看见如今的西方“民主”国家的惨状,在看看我们国家如今的生机盎然,实在感觉自己生在了一个好国家,为自己是中国人感到自豪。同时我也感谢我的父母,为我提供了如此好的环境,让我能坐在家中清闲的,观察这个世界,谢谢他们的陪伴与鼓励。也感谢我的女友,是她让我找到了奋斗的方向,然我能够认识到自己的不足,让我不断的进步。也感谢,沈逸老师,陈平老师,张维为老师在整个2020年给我带来了无限的思考,你们是我快乐的源泉。2020年开心的事情有很多,同时也有然我伤心的事情,重阳的时候我爷爷去世了,享年81岁,我心中感情复杂,有悔恨,也有伤感,有感慨,也有思念,但相对来说我比较平静,能接受亲人的离去。在此我悼念我的爷爷,他不是一个特别友好的人,但一定不是坏人,他很倔强,但同时他也很自律,他这种自律是一般人无法学会的,至少我很佩服,能想象一个抽了几十年烟的人,说不抽烟就不抽烟,每天中午都要喝一杯酒的人,说不喝酒就不喝酒。我应当向他学习,学习他的这种自律。我爱您我爷爷。

展望未来

接下来一年还是任务艰难的,考研成了我的头等大事,学习了毛泽东的思想,抓住主要矛盾,先解决主要矛盾,再解决次要矛盾,现在的主要矛盾就是学习上的困难和考研的矛盾。必须要克服困难,考上研究生,学的越多,越发现自己其实很菜,首先承认这一才是基础,但我很兴奋,菜说明还有更多东西能学,我意识到自己菜,说明我知道有很多东西可以学,也有我想学的东西,我也相信自己的学习能力。努力复习,坚决考上研究生,报效祖国。

关于c++中stl库的sort模板的理解

今天浮于表面的研究了以下STL库中sort方法,从新思考了以下sort方法中穿回调函数应该怎么用数学方法理解

先来看一下形式

default (1)    
template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)    
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

下面是具体代码

// sort algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector

bool myfunction (int i,int j) { return (i<j); }

struct myclass {
  bool operator() (int i,int j) { return (i<j);}
} myobject;

int main () {
  int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

  // using object as comp
  std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

从上面的代码中可以看出传入的回调函数是一个bool返回值的,具体的细节我不清楚,源码的阅读理解会在后续展开,但是就从快速使用上来说,如何理解这个回调函数的意义?先来看看c++官网是如何解释的:Binary function that accepts two elements in the range as arguments, and returns a value convertible to bool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.(返回的值指示作为第一个参数传递的元素是否在其定义的特定严格弱顺序中位于第二个参数之前)
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.*
其中重要的一句话是:
返回的值指示作为第一个参数传递的元素是否在其定义的特定严格弱顺序中位于第二个参数之前
我可以理解为这个回调函数其实是一个数学条件,我理解为sort是按照如此这般的方法去规范自己排序的依据,并且对所有的元素都应该是遵守这个依据的,如果两个元素比较的时候没有遵守这个依据,就交换位置

如何用数学语言去描述呢?

我比较喜欢用数学的方法去描述,这样更简单且方便理解一点。这个回调函数其实可以描述成一个数学表达式:∀i,j,其中i!=j,都有 bool comp(i,j)== true
而对整个sort函数运行结构的数学描述则是:在数组num中,i∈num,j∈num,i!=j,∀i,j,都有 bool comp(i,j)== true

总结

当用数学描述出来后会发现,相当的好理解,也好记忆了(也可能是我自己个人的感受),以后的算法设计也可以按照这种想法来:先提出数学表达式,以此为目的,设计出符合自己目的的算法来。从这里我也理解出,算法其实是实现目的的手段,而正真的难点是如何抽象你所需要实现的东西,当你抽象出来后,算法的复用性可大大增加,否则会增加很多工作量。算法是服务与人类的,算法本身不美,美的是背后的思想,和伟大的人。

如何安装opencv4到ubuntu18.04

如何安装opencv4到ubuntu18.04

查找了相当一部分的资料后终于成功编译好了opencv(C++)

引言

网上很多教程其实不能完全编译好opencv4.0.0这个版本,当你开始编译自己的opencv时,各种问题会随之而来,比如编译的时候出现缺少静态链接库,甚至有的时候编译源代码时命名空间有问题都得自己更改。所以写这篇文章时为了让更多的人避免一些坑我会细细地讲解一下编译的过程

第一步选择操作系统和语言

我选择的时ubuntu18.04,不同操作系统所需的库不同,我只实验了ubuntu18.04,并且我只针对用c++编写,所以使用python或java的朋友,需要查阅相关资料。(注意不要使用虚拟机)

第二步联网

安装环境需要连接真正的互联网,否则下载安装包的速度会非常的慢,甚至会失败,所以找到一个好的代理服务器是必须的。

第三步安装环境

创建一个文件夹--opencv

mkdir opencv && cd opencv
nano opencv_environment.sh

复制下面内容到opencv_environment.sh

echo "OpenCV installation by learnOpenCV.com"
# Define OpenCV Version to install 
cvVersion="master"
# Create directory for installation
mkdir installation
mkdir installation/OpenCV-"$cvVersion"
# Save current working directory
cwd=$(pwd)
sudo apt -y update
sudo apt -y upgrade
sudo apt -y remove x264 libx264-dev

## Install dependencies
sudo apt -y install build-essential checkinstall cmake pkg-config yasm
sudo apt -y install git gfortran
sudo apt -y install libjpeg8-dev libpng-dev

sudo apt -y install software-properties-common
sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu xenial-security main"
sudo apt -y update

sudo apt -y install libjasper1
sudo apt -y install libtiff-dev

sudo apt -y install libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev
sudo apt -y install libxine2-dev libv4l-dev
cd /usr/include/linux
sudo ln -s -f ../libv4l1-videodev.h videodev.h
cd "$cwd"

sudo apt -y install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
sudo apt -y install libgtk2.0-dev libtbb-dev qt5-default
sudo apt -y install libatlas-base-dev
sudo apt -y install libfaac-dev libmp3lame-dev libtheora-dev
sudo apt -y install libvorbis-dev libxvidcore-dev
sudo apt -y install libopencore-amrnb-dev libopencore-amrwb-dev
sudo apt -y install libavresample-dev
sudo apt -y install x264 v4l-utils
sudo apt-get -y install libvtk7-dev

# Optional dependencies
sudo apt -y install libprotobuf-dev protobuf-compiler
sudo apt -y install libgoogle-glog-dev libgflags-dev
sudo apt -y install libgphoto2-dev libeigen3-dev libhdf5-dev doxygen
sudo apt -y install python3-dev python3-pip
sudo -H pip3 install -U pip numpy
sudo apt -y install python3-testresources
# Fix failed to load module “canberra-gtk-module”
sudo apt install libcanberra-gtk-module libcanberra-gtk3-module
# install qtcreator
sudo apt-get install qtcreator -y

给脚本运行权限并运行

chmod +x opencv_environment.sh
./opencv_environment.sh

第四步下载opencv4.0.0和opencv4.0.0_contrib-4.0.0(在opencv文件夹中)

wget "https://github.com/opencv/opencv/archive/4.0.0.tar.gz" -O opencv.tar.gz
wget "https://github.com/opencv/opencv_contrib/archive/4.0.0.tar.gz" -O opencv_contrib.tar.gz
# 解压到本地
tar -zxvf opencv.tar.gz
tar -zxvf opencv_contrib.tar.gz

第五步编译opencv4.0.0

在opencv文件中创建一个脚本

nano opencv_build.sh

复制以下内容到opencv_build.sh

rm -rf build
mkdir build && cd build
cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.0.0/modules ../opencv-4.0.0 -DOPENCV_GENERATE_PKGCONFIG=ON -DWITH_TBB=ON -DWITH_V4L=ON -DWITH_QT=ON -DWITH_VTK=ON -DWITH_OPENGL=ON #打开了qt和opengl模块,可以用qt和opengl的库
make -j8 #-j8代表8个线程编译
make install

给opencv_build.sh运行权限

chmod +x opencv_build.sh

先别急着运行,在opencv_contrib-4.0.0中对应的qt模块源码有一处错误,这个错误会导致你在编译到68%的时候报错,原因是没有使用正确的命名空间。

到这个文件下面opencv/opencv_contrib-4.0.0/modules/cvv/src/qtutil/filter
有一个名叫 sobelfilterwidget.cpp 的源文件在第11行下面添加一行 using namespace std; 即可

运行opencv_build.sh

./opencv_build.sh

紧接着就静静等待安装完成,

一些细节

编译完后安装的根目录是/usr/local/

/usr/local/bin - executable files
/usr/local/lib - libraries (.so)
/usr/local/cmake/opencv4 - cmake package
/usr/local/include/opencv4 - headers
/usr/local/share/opencv4 - other files (e.g. trained cascades in XML format)

总结

内容有很多细节没有讲,但都在文章里面,opencv对初学者不是很友好,本人也是花了将近一个月的时间,不停的换操作系统,不停的在虚拟机和真机中切换,最后发现很多东西虚拟机和真机有不同,所以劝朋友们最好不要使用虚拟机,直接使用真机。不同的操作系统需要的环境不同,理论上按照上面的步骤是可以配置成功的,但实际上本人只在ubuntu18.04这个版本上成功过。时代在发展,本教程只做参考。

如果遇到问题请邮件联系或者在下方留言
邮箱:zhengngago@gmail.com