- 博客(81)
- 收藏
- 关注
原创 Qt GUI程序中主线程与非主线程之间的通信
Qt应用程序exec后就会生成一个线程,这个线程就是主线程,在GUI程序中也称为GUI线程。主线程也是唯一允许创建QApplication或QCoreAppliation对象,比并且可以对创建的对象调用exec()的线程,从而进入事件循环。 在只有主线程即单线程的情况中,每一个事件的发生都需要进入事件循环进行等待,如有在某一步计算量比较大,则会一直占用CPU不放,导致其它操作无法完成,界面陷入冻结
2015-12-04 09:45:27 9824 4
原创 二叉树的深度
一般二叉树的算法很容易地想到使用递归。在求一棵二叉树的深度时,我们判断根结点,如果根节点存在,则可以将问题转换成:求该根节点的左右子树中深度较大者+1。 代码如下:class Solution {public: int TreeDepth(TreeNode* pRoot) { int leftDepth, rightDepth; if(pRoot
2015-09-15 20:23:10 704
原创 2015华为机试题
一般二叉树的算法很容易地想到使用递归。在求一棵二叉树的深度时,我们判断根结点,如果根节点存在,则可以将问题转换成:求该根节点的左右子树中深度较大者+1。 代码如下:class Solution {public: int TreeDepth(TreeNode* pRoot) { int leftDepth, rightDepth; if(pRoot
2015-09-13 11:32:31 1143
原创 Linux中静、动态函数库的优缺点
在编写程序的时候,我们经常会使用到函数库。函数库即为一个事先已经写好的函数的集合,其性能都是比较优秀并得到公众认可的。而我们在需要实现一些功能的时候,如果函数库里已经有该功能的实现函数,则我们可以直接使用函数库中来实现,而无需再重新编写程序代码。 在Linux操作系统中,函数库根据是否被编译到程序内部而分为静态函数库和动态函数库。静态函数库扩展名(.a)编译行为 静态函数库在编译的时候会被直
2015-09-09 11:00:00 1183
原创 动态规划之最长不下降子序列
动态规划的思想就是需要在求得最优解的过程中保存中间结果。在求最长不下降子序列的过程中,我们需要保存每个子序列,然后继续往后判断时将当前元素添加到小于该元素并且最长的子序列当中。譬如有序列2、1、3,首先有一个序列2;然后判断1的时候,前面没有比1小的子序列,因此1独自成为一个序列;最后在判断3的时候,前面的两个子序列2和1都比3小,并且这两个子序列的长度也相等,这个时候两个都满足了,我们暂且就保存一
2015-08-31 08:46:47 5352
原创 Maxinum Subarray
题目描述:Find the contiguous subarray within an array (containing at least one number) which has the largest sum. 输入:the array([−2,1,−3,4,−1,2,1,−5,4]) 输出: the largest sum(6) PS. for the array [4,−1,2,
2015-08-30 21:42:17 583
原创 动态规划之合唱队形问题(最长递增子序列变形)
题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。合唱队形定义:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,则他们的身高满足T1 < T2 < … < Ti, Ti > Ti+1 > … > TK (1 <= i <= K)。 要求:已知所有N位同学的身高,计算最少需要几位同学出
2015-08-30 20:08:02 7075
原创 Linux中的用户切换(root授权)
Linux是一个多用户系统,但是其中只有一个超级用户root,root用户拥有许多的特权,例如可以执行一些系统命令,查看/etc/shadow等一些配置文件。而普通用户一般只能够在自己的home里面进行一些操作,或者可以进入一些其它文件查看,但是一般都不能对其进行任何修改操作。所以我们以普通用户登录进行一些操作的时候经常会碰到“Permission denied”这样子的错误提示,即权限不允许。这样
2015-08-28 19:59:33 12765
原创 Linux中的硬链接和软链接
在Windows操作系统中,我们经常会给一个文件创建一个快捷方式到桌面上,给其取一个自定义的文件名,然后可以通过该快捷方式来操作该文件,比较方便地共享了该文件。在Linux中也有类似快捷方式的方法来实现文件的共享,分别是文件的硬链接和软连接。硬链接我们知道在Linux的文件系统中,一个文件在磁盘分区中对应一个inode和多个block,inode用来记录文件的属性信息,而block用来存放文件的
2015-08-27 11:27:35 2200
原创 Linux默认shell—bash shell的优点
在Linux操作系统中,用户没有办法跟内核直接交流,内核能够控制硬件的操作,并且向外提供系统调用接口,而在系统调用之上,可以有公用函数库,可以直接被应用程序调用,同时也可以有我们的shell。shell的概念很广泛,它并不是Kernel的一部分,shell本身是一个用C程序编写的程序,它可以作为一种命令语言或一种程序设计语言,是一种脚本语言,根据语法和执行方面不同,其解释器也不同,常用
2015-08-23 22:33:45 6135
原创 网易内推电话面试(一面)
昨天晚上十点多的时候接到网易的内推电话面试,投了简历已经很长一段时间了,其实我都已经放弃了,接到电话的时候有点突然,一点心理准备都没有,但是也只能硬着头皮面了。主要都是根据简历问的问题,内容大概都是C++、网络和Linux三大块,我把我记得的问题整理出来如下:Linux系统从通电到运行应用程序的整个过程;(从启动BIOS到main的启动例程)Linux中fork()较Windo
2015-08-22 10:34:16 8144
原创 Qt鼠标事件 我的鼠标样式
鼠标样式的效果如下:主要思路:重写widget的MouseMoveEvent事件的处理函数。移动过程中的四个星星由四个定时器控制着,分别处于移动前位置A点和移动后的位置B点之间的四点上,然后从最小的星星到最大的星星分别在定时器事件中消失。关于起点A和重点B的位置保存问题,在mouseMoveEvent函数中,有pos()获取到的坐标是移动此刻的坐标。
2015-08-21 20:49:01 848
原创 Qt中使用事件过滤器来处理键盘焦点
我们都知道,在主事件循环中,使用QApplication::notify(QObject*, QEvent*)来分发时间到下面的子窗口,而子窗口将调用QObject::event(QEvent*)来根据事件类型调用相应的事件处理函数。在处理键盘焦点的时候,我们把焦点定位特殊部件的习惯通常是Tap键、下一个键盘快捷键或者鼠标滚轮等等,根据传统的方法,为了能够正确切换焦点,我们需要重写每个部件的键盘处
2015-08-20 22:08:43 3787
原创 在QT中使用TCP协议进行文件传输(可以单向循环传输)
大致步骤如下:1、服务器端设置监听套接字,开始监听;2、客户端在连接成功时开始传送文件,有connected()信号连接send()槽,send()发送文件头信息,包括文件名、文件总大小和文件名大小等;3、传送完文件头信息时开始传送文件内容,有bytesWritten(qint64)信号连接到goOnSend(qint64)槽,前者是当想套接字写入数据时会出发的信号,即当已经想套接字写
2015-08-19 20:31:40 12768 6
原创 随机数与随机种子
对随机数的使用较少,因此没有深入了解过其产生原理。这里涉及到两个函数,rand()和srand(),前者是生成一个伪随机数,后者是生成一个随机种子。一、rand()rand()可以生成一个0~RAND_MAX之间的一个随机数,返回值是一个unsigned int类型值。如下代码:#include #include #include using namesp
2015-08-15 11:16:28 38153 6
原创 经典排序算法之快速排序
快速排序的基本思想是,从带排序的序列中选取一个关键字作为基数,然后经过一轮排序,将比基数大的关键字放置在左侧,将比基数小的关键字放置在右侧。然后再两侧的中间便是此基数的位置,然后再将此基数的两边继续进行快速排序。从上面可以得知,每一趟快速排序都能够确定一个关键字的位置。对于每一趟的关键字与基数的比较以及移位,我们的方法如下:最后当low和high
2015-08-14 21:44:26 705
原创 线程同步之条件变量
进程空间中有一个存储量A,该进程空间内存在多个线程,这多个线程都会访问到A,或读或写,为了保障每个线程当前读到的是正确的A而不是别的线程正在修改过程中的A,我们在访问A之前需要对A进行加锁,使得我们在访问A的时候别的线程禁止访问A,这是互斥量锁。或者允许多个线程同时读A,这是读写锁。还有一种情况,有些线程也需要访问A,但是它只是想在A达到某个值的时候才做一些事情,即值关心达到某种状态下的A。比如线
2015-08-14 16:35:04 433
原创 线程属性:pthread_addr_t
在多线程环境下,有很多对象,像是线程、互斥量等,我们需要使用这些对象来调整和同步线程,因此,这些对象需要包括很多的特征属性,我们为每种对象设计了一种属性结构,属性结构可以包括多个属性。然后可以将属性结构对象与对象相关联,我们就可以通过调整属性来处理线程。我们为每种属性结构设计了同一套使用模式,包括:属性对象与线程对象关联、初始化属性对象、销毁属性对象、获取属性对象里面的具体某个属性值、设置属性对象
2015-08-13 21:06:53 922
原创 Linux进程的实际用户ID和有效用户ID
在Linux中,每个文件都有其所属的用户和用户组,默认情况下是文件的创建者,也可以根据chown和chgrp来修改文件所属的用户和用户组。文件的属性存放在属性结构stat中,其中有st_uid和st_gid标志着。先举个例子。假设现在系统中有两个用户liz和hlf,有一个程序文件file的所属用户为hlf。然后使用liz用户登录系统,运行file文件,则运行进程process有一个实际
2015-08-10 19:05:03 4690 1
原创 动态规划之矩阵连乘问题
在动态规划算法中,局部最优并不一定会使得全局最优,它在每一个阶段的决策都会影响到后面的决策。所以我们在将问题划分为若干阶段时,需要将各个阶段所发生的不同状态存储起来,提供后一阶段做决策。一般都是子问题重叠的时候使用动态规划。下面是一个矩阵连乘的问题。问题:n个矩阵连乘问题描述:矩阵连乘满足结合律,在n个矩阵连乘时,什么样的结合方式可以使得整个过程中所做的乘法次数最小。数量化:记 Mi
2015-08-10 11:23:11 1227
原创 STL之map操作的几点疑惑
一、map下标操作所导致的初始化(副作用)当在程序中使用下标操作时,会发生什么呢?下标代表的是键,当这个键在map中已经存在的话,则下标操作可以获得该键所关联的值;当这个键在map中不存在的话,将执行下面的操作:1、调用值类型mapped_type的默认构造函数来初始化与该键关联的值,再将这个键值对插入到map中;2、然后再在新的map中获取该键关联的值来执行用户的
2015-08-09 17:29:09 1117
原创 经典排序算法之堆排序
首先介绍堆的定义:堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。由于堆的表象结构是一棵完全二叉树,我们称之为二叉堆。下面分别就是两个大顶堆和小顶堆:随后我们都是以大顶堆为例来介绍堆排序的,小顶堆也是一样的。对于大顶堆,我们直到,根结点肯定是整个堆中最大的结点,
2015-08-07 18:01:41 689
原创 经典排序算法之希尔排序
前面的直接插入算法,以抓牌为例,假设手气比较好,抓牌的顺序是从A直到K,那么在这整个过程中都无需进行任何的插入动作,只需要将每次抓到的牌放在最后即可。假设现在手上已经抓到的牌的顺序中逆序比较少,则抓牌的过程中插入操作就越少。因此,对于基本有序的序列排序,直接插入排序的性能是比较好的。这里的基本有序是指较大的数据尽量在后面,而较小的数据尽量在前面。为了使得直接插入算法更加有效,我们可以在最后使用插入
2015-08-07 15:34:15 797
原创 重温《C++ Primer》笔记十 当数组作为函数参数时
提到数组作为实参,大家可能都会想到,数组是不能复制的,所以作为参数时不能真正得到实参数组。另外,使用数组名字的时候,编译器会自动将其视为指针,因此它实际获得的是实参数组中首个元素的地址。没错,对于非引用数组参数是这样,但是对于引用数组参数则是可以实现真正的数组传递的。一、非引用数组形参,[]和长度值的作用当以数组形式作为函数参数时,首先,[]的作用是告诉编译器这是个
2015-08-06 21:19:00 813 1
原创 经典排序算法之直接插入排序
插入排序的过程与我们平时抓牌的过程非常类似。每次抓一张排,然后与手上已有的牌逐个进行比较,找到其合适的插入位置。一、直观插入排序算法完全按照直接插入排序算法来编写代码,需要另外开辟一个与原数据相同的存储空间。将这个过程量化:假设有原序列有n个数据元素。第一个元素无序插入,因此需要插入n-1次。每次插入过程中,从后往前,遇到比自己大的就将此大的
2015-08-06 20:35:13 916
原创 经典排序算法之简单选择排序
前面在介绍冒泡排序的时候,有提到一种简单排序算法,就是从0开始,每次确定一个位置的元素。假设当前需要确定的位置下标为i,则将i处的元素与后面的元素逐个比较,并将每次比较结果中较小的元素存放在i处,从而保证i处一直保存着最小元素。简单的选择排序算法与这种算法思路一样,但是选择排序在比较的过程中,并没有将比较结果存放在i处,而是保存每次比较结果中较小元素的下标到min中,从而保证m
2015-08-06 19:19:51 18999 1
原创 经典排序算法之冒泡排序
冒泡排序,顾名思义,就是想冒泡一样,较大的泡泡或者较小的泡泡会往某个方向移动,直到所有的泡泡有序为止。一、简单排序实现在给出正宗的冒泡排序之前,我们来看一种简单的冒泡排序(以升序为例)。假定一定一个无序序列,从第一个位置开始,将此位置的元素与后面所有无序的元素逐个进行比较,只要是比这个位置的元素值小的元素,就与这个位置的元素互换值,直到序列末尾。因此,我们可以确定这个位置的
2015-08-06 18:24:41 942
原创 C/C++在线笔试题总结(持续更新)
下午在牛客网上试做了一下2015校招研发岗位的笔试题,错了蛮多的,这里总结一些题目吧。1、不算main这个进程,到底创建了多少个进程?int main(int argc, char* argv[]){ fork(); fork() && fork() || fork(); fork();}解析:主要考虑到两点:第一,对于fork()函数,在父进程中返回子进程ID,
2015-08-05 16:46:14 1488
原创 利用tcpdump抓包工具监控TCP连接的三次握手和断开连接的四次挥手
TCP传输控制协议是面向连接的可靠的传输层协议,在进行数据传输之前,需要在传输数据的两端(客户端和服务器端)创建一个连接,这个连接由一对插口地址唯一标识,即是在IP报文首部的源IP地址、目的IP地址,以及TCP数据报首部的源端口地址和目的端口地址。TCP首部结构如下:其中在TCP连接和断开连接过程中的关键部分如下:1.源端口号:即发送方的端口号,在TCP
2015-08-05 08:20:34 5039
原创 TCP套接字编程—具体流程梳理
一个上午都在调试一个服务器端监听程序,测试的客户端怎么都连不上,然后疯狂在网上搜寻答案无果,最后无意中发现竟是系统没有联网。唉,顿时就像是在debug过程中发现某处少了一个逗号是一个样的郁闷!不过这个纠结的过程却让我把TCP套接字编程的整个过程又有了重新的认识。TCP是一种可靠的面向连接的通信协议,因此在通信之前需要确认通信的双方,称之为客户端和服务器端。一般由客户端向服务器端发送连接
2015-08-04 12:07:24 10553
原创 套接字&套接字地址结构和bind()函数
我们都知道在网络编程中,可以调用socket()函数来获取一个套接字描述符。但是,socket()函数的作用只是返回一个很小的非负整数值吗?并非如此,socket()函数的作用是创建套接字的。创建套接字的流程如下socket()函数会触发内核调用sys_socket()函数,然后sys_socket()函数会调用sock_create()函数。此函数会根据我们在
2015-08-03 22:35:38 4734 1
原创 Unix中的僵尸进程
现实中的僵尸是一种似死非死的状态——一直在人间四处游走,但是却不能做一些活人能做的事情。而对于僵尸进程,与这个有些类似,它不能向一般进程那样来执行程序、被调度而占用CPU,但是它却不能消失,因为它还没将它的“死讯”告诉它的父进程和系统,它得让别人知道它已经死了,免得别人还来找它干活它却啥都不能干。我们需要了解到,进程的终止是一件异步事件,即是一件可能随时都会发生的事情。
2015-07-30 10:18:55 924
原创 在子进程中调用exit()函数对标准I/O流的影响
我们知道exit()函数是用来终止程序用的,它将调用exit系统调用,将程序状态作为参数返回给内核。但是之于_exit()和_Exit(),exit()的不同之处在于,exit()在调用exit系统调用之前,它将做一些最后的处理,包括两个部分:调用由atexit()注册的终止处理程序;关闭打开的流。这里我们要讨论的是第二点。fork()我们都知道,由fork()创建的子进程是父进程的副
2015-07-28 16:19:44 2475
原创 fork()、COW和vfork()的区别
一个进程可以通过调用fork()或者vfork()函数来创建一个新进程,调用进程被成为父进程,产生的新进程叫做子进程。而在调用(以fork()为例)fork()的时候,会产生两个返回值,一个是返回给父进程,另一个是返回给子进程。而用户可以通过返回值来判断哪个是父进程,哪个是子进程。在子进程中返回值为0,而在父进程中的返回值为子进程ID。这种安排是有理由的。一个进程可以有多个子进程,但是却只能有一个
2015-07-28 15:26:20 2122
原创 Linux中C程序的存储空间布局 & C++的五大存储空间
Linux中C程序的存储空间布局可以从《APUE》上面摘得下图所示,即为Linux中C程序的存储空间布局情况。从低地址到高地址依次分为五大部分1.正文段。即为代码段,它存储的是CPU执行的机器指令,这部分是共享的,即存储其中只有正文段的一个副本。另外,正文段一般都是只读的,防止程序意外修改其指令。2.初始化数据段(数据段)。这段存储空间主要存放的是全局作用域中明
2015-07-27 22:40:04 906
原创 Linux环境中程序的始终
首先由内核使程序执行。内核首先创建一个启动例程,然后调用exec函数使得该启动例程执行。然后启动例程从内核中取得命令行参数和环境变量值,用来调用main函数。于是开始执行main函数。在main函数中可以调用用户函数,然后可以从用户函数中通过return语句返回其主调函数。当然,我们还可以随时使得程序终止,即通过调
2015-07-27 20:56:51 439
原创 Qt同步线程的几种方法
一、QMutex类QMutex类就像一把锁,在互斥量之前上锁(QMutex::lock()),然后在使用完互斥量之后解锁(QMutex::unlock())。比如下面的代码:void someMethod(){ mutex.lock(); qDebug()<<"Hello"; qDebug()<<"World"; mutex.unlock();}
2015-07-27 09:14:56 5378
原创 7月份复习总结&8月份复习计划
时间过得很快,转眼间7月份就要过去了。这个7月对于我来说还蛮平静的,身边没有想象中那样充斥着关于秋招的各种信息,大家好像都蛮安静的。我基本上每天都在看书,但是每天的基调心情还是担心忧虑,总感觉自己不行,感觉有看不完的书,做不完的题,特别是在leetcode上面实在是受了太大的打击了。好吧,还是让心情暂时slow down下来,给自己总结一下吧,不然真乱了阵脚就糟糕了。完成情况 1、
2015-07-27 09:03:50 784
原创 重温《C++ Primer》笔记九 const形参小结
首先,形参大致可以分为三种:非引用形参、引用形参和指针类型形参。一、非引用形参在传递参数的时候,不论是所谓的传值还是传址,实际上都是实参值到形参值的复制,其中的区别只是复制的是普通对象还是引用对象而已。对于非引用形参,通过参数传递之后,形参是实参的一个副本,而非引用形参使得复制后形参与实参并没有任何关联,因此,在函数中对形参的任何操作将不会影响到实参的值,因此,不论实参是变量还是常
2015-07-05 10:36:52 699
原创 重温《大话数据结构》笔记一 单链表链式存储结构的操作代码
#include #include using namespace std;typedef int ElemType;//单链表的链式存储结构typedef struct Node{ ElemType data; //数据域 Node *next; //指针域}Node;typedef Node* LinkList;//线性表的类型操作(operation)void
2015-07-03 16:55:13 563
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人