算法经典问题之第k大/小问题(寻找中位数)

算法经典问题之第k大/小问题(寻找中位数)

问题描述

从n个未排序的数中找出第k小的数。
有直接解法是先排序再拿第k个数即可,但是最好的算法也要(O(n\lg{n}))。
下面的解法更优。

解法

这个其实是利用的分治法思考,和二分查找很像。
和快速排序同样的过程,先随机选一个数,然后把比它小的放到左边,比它大的放到右边。设排完后这个数的索引是m,
对比m和k,
如果m==k,说明这个数就是我们要找的。
如果m<k, 说明前m个数都比要找的数小。从而问题变为从右边的数中找到第k-m小的数。
如果m>k,说明要找的数在前m个数中,从而问题变为从右边的数中找到第k小的数。

按此算法,它的时间效率是O(n)。

python实现

#!/usr/bin/env python
import random


def min_k(data, k):

    def swap(i, j):
        temp = data[i]
        data[i] = data[j]
        data[j] = temp

    n = len(data)
    s = random.randint(0, n-1)
    swap(s, 0)
    j = 1
    key = data[0]
    for i in range(1, n):
        if data[i] < key:
            swap(j, i)
            j += 1
    swap(j-1, 0)
    if j == k:
        return data[j-1]
    elif j > k:
        return min_k(data[0:j-1], k)
    else:
        return min_k(data[j:], k-j)

数据结构之哈稀表

数据结构之哈稀表

前言

哈稀表在工作中常用,语言都内置有,对应于字典或者对象。
首先得定义一些操作。我有一组数据,每个数据x有key=>value这样的结构。
操作1, 插入一对新的x到这个集合中。
操作2,删除这个集合中的x.
操作3,搜索这个集合中key为k的x。

最简单的实现

直接映射表。
要求这些x的key是在有限集合中,并且是不重复的,如U = {0,1,…m-1}
你只需要建立一个数组,key为索引,值为value就可以了。

但他的问题是可能m很大,但要操作的数据很小,这样这个数组就会很稀。

哈稀的引入

所谓的哈稀法,就是用一个哈希函数H来随机映射那些键。

其实就是针对上面直接映射表的。即然key的集合很大,那我就通过一个函数把这个key的集合映射到一个比较小的集合上。
但这会引入另一个问题,从大集合到小集合,一定存在着多个key映射到同一个值的情况。这被称为碰撞。

链表法解决碰撞

解决办法就是在新的小集合上,new-key存放的并不是x,而是一个存放有x的链表。当要查找时,就遍历这个链表,对比key和x.key即可。

但这种实现在最坏情况下访问效率很低。
最坏情况是所有key映射到同样的一个new-key,这时候就只剩下一个链表了,查找效率是(\theta(n))

从这可看出哈希的关键是选取恰当哈希函数H, 使得key能均匀地哈希到new-key。
装载因子>1, 即平均每个槽放的元素>1.

开放寻址法解决碰撞

这种方案不是使用链表,而是在第一次哈希后,如果遇到碰撞则再哈希一次看看,如此形成一个哈希序列,也叫探查序列。
好处是不需要增加额外的数据结构,不需要修改元素。缺点是删除不好处理,如果直接删除,则原来因为碰撞而需要再次探查的数据会误以为元素不在哈希表中。

装载因子(\alpha)<1, 即平均每个槽放的元素<1.预期探查次数是( \frac{1}{1-\alpha} )
探查序列有两种方案。

线性方法

[h(k, i) = (h(k, 0) + i)\ mod\ m]
h(k, i)表示对k的第i次探查。

这种方法简单,但是容易遇到集群现象,即当碰撞时,会在局部集中有值。

二次哈希

这种在实践中比较实用。
[h(k ,i) = (h_1(k) + i * h_2(k))\ mod\ m]
其中(m= 2^r), h_2(k) 为奇数。

哈希函数的选择

除法

h(k) – k mod m (m是新集合的大小)
这里m不能太小,最好是质数。

乘法

m是(2^r), 机器字长为w。
[h(k) = (A*k\ mod\ 2^w)\ rsh\ (w-r)]
A为介于(2^{w-1})到(2^w)之间的某个奇数。 rsh表示右移操作。
因为CPU有指令直接可以得到两个w相乘后的低w位,mod和rsh都是位移操作。所以这个算法相对上面的除法效率要高。

高级主题

哈希的问题

因为哈希是从一个大的集合哈希到一个小的集合,那么对于任意一个哈希函数来说,
都存在一个不好的key集合,都会哈希到同一个槽。

全域哈希

为了解决上面的问题,我们从哈希函数的集合中采取随机的哈希函数,这就叫做全域哈希。这里要求选取随机哈希函数的有限集有一个规律:当从中随机选择两个哈希函数时,他们哈希到同一个槽的概率是1/m。

做法

这里有个前提,选择槽数m为质数。
把key按m进制表示为(<k_0, k_1, …k_r>).
再随机选择一个数a, 也按m进制表示为(<a_0, a_1, a_2…a_r>)
定义(h_a(k) = (\sum_{i=0}^{r}a_iK_i)\ mod \ m)

完全哈希

完全哈希是用来处理静态哈希表。
有两个要求:
1. m = O(n)
2. 在最坏情况下查找的时间效率是O(1)

做法

用二级结构。并且每级结构都用全域哈希。
假设在第一级第i个槽有(n_i)个元素发生碰撞,则二级结构的大小是(n_i^2)

python标准库difflib介绍

python标准库difflib介绍

简介

从python2.3起difflib成为了标准库。无需安装即可使用。
之前遇到一个问题,我本地的代码没有问题,而服务器上的则一直报404错误。肉眼对比了一下路径,感觉是完全一样的。在网上找了下字符串对比工具,没有一个好用。
后来还是有个同事眼力好,发现有个一字符的大小写问题导致的。那会如果知道python有difflib库的话,早就把问题解决了。

简单的对比

以下示例是一个相当简单的代码。

import difflib

text1 = """
<!-- 
Template Name: Metronic - Responsive Admin Dashboard Template build with Twitter Bootstrap 3.3.6
Version: 4.5.4
Author: KeenThemes
Website: http://www.keenthemes.com/
Contact: support@keenthemes.com
Follow: www.twitter.com/keenthemes
Like: www.facebook.com/keenthemes
License: You must have a valid license purchased only from themeforest(the above link) in order to legally use the theme for your project.
-->
"""

text2 = '''
<!-- 
Template Name: Metronic - Responsive Admin Dashboard Template build with Twitter Bootstrap 3.3.6
Version: 4.5.5
Author: alston 
Contact: support@keenthemes.com
Follow: www.twitter.com/keenthemes
Like: www.facebook.com/Keenthemes
Purchase: http://themefrest.net/item/metronic-responsive-admin-dashboard-template/4021469?ref=keenthemes
License: You must have a valid license purchased only from themeforest(the above link) in order to legally use the theme for your project.
-->
'''

text1_lines = text1.splitlines()
text2_lines = text2.splitlines()

d = difflib.Differ()
diff = d.compare(text1_lines, text2_lines)

print('\n'.join(list(diff)))

输出示例:

<!–
Template Name: Metronic – Responsive Admin Dashboard Template build with Twitter Bootstrap 3.3.6
– Version: 4.5.4
? ^

看着真是费劲,-,+,?,。能感觉出来-是少了,+是增加了,?和表示存在差异。

试试html美化的

修改比较简单。只要把

d = difflib.Differ()
diff = d.compare(text1_lines, text2_lines)

print('\n'.join(list(diff)))

替换成

d = difflib.HtmlDiff()
print(d.make_file(text1_lines, text2_lines))

即可。

看着还不错。会用颜色标识出来。

更多对比工具

标准库里还有个filecmp库,支持单文件对比,多文件对比,目录对比。

运维管理工具fabric详解

运维管理工具fabric详解

前言

运维管理工具有fabric,ansible等等。
本节讲下fabric,最开始接触是在廖雪峰的文章里。他用fabric做的运程部署。
这里打算详细了解下。
官网点击这里。

安装

这个真没啥讲的。我都是pip install fabric.
不过现在还不支持3.x, 所以还是请用virtualenv吧。

文件

执行fab命令时,默认会使用fabfile.py, 如果你的文件名不是这个,请使用-f参数。
fab -f yourfile.py

fab的常用参数

可以通过fab -help查看

  1. -l 显示定义好的任务函数名。
  2. -f 指定fab入口文件
  3. -g 指定网关(中转)设备,比如堡垒林环境,填写堡垒机IP即可。之前在新浪和腾讯工作时,他们都有跳板机/堡垒机。 阿里云的金融云模式也提供堡垒机。
  4. -H 指定目标主机,多台主机用”,”分隔;
  5. -P, 以异步并行方式运行多主机任务,默认为串行运行。
  6. -R, 指定role, 以角色名区分不同业务组设备。
  7. -t, 设置设备连接超时时间(秒).
  8. -T, 设置远程主机命令执行超时时间(秒);
  9. -w, 当命令执行失败,发出告警,而非默认中止任务。

可以不写一行python代码也可以完成简单的远程操作,直接使用命令行的形式,例如。

fab -u 用户 -p 密码 -H 主机IP -- 'uname -s'

结果
[123.57.145.149] Executing task ”
[123.57.145.149] run: uname -s
[123.57.145.149] out: Linux
[123.57.145.149] out:
Done.
Disconnecting from 123.57.145.149… done.

fabfile的编写

全局属性设定

在命令行中的参数如 -u -p 等可以通过env对象来设定。
env对象的作用是定义fabfile的全局设定,支持多个属性,包括目标主机、用户、密码、角色等,各属性说明如下:

  • env.hosts, 定义目标主机,可以用IP或主机名表示,以Python的列表形式定义,如env.hosts = [‘192.168.1.21’, ‘192.168.1.22’]
  • env.exclude_hosts, 排除指定主机,如env.exclude_hosts=[‘192.168.1.22’]
  • env.user, 定义用户名, 如env.host=”work”
  • env.port, 定义目标主机端口,默认为22, 如env.port=”22″.
  • env.password, 定义密码,是对应user的密码.如env.password=”password123″,这里密码太弱,只是说明一下用法.
  • env.passwords, 与password功能一样,区别在于不同的主机不同密码的应用场景,需要注意的是,配置passwords时需配置用户、主机、端口等信息,如
env.passwords = {
'root@192.168.1.21:22':'fdsfsf',
'root@192.168.1.22:22':'dfsfsfsafsafas',
'root@192.168.1.23:22':'ppopojpoj[p'
}
  • env.key_filename 可以通过pem文件登录。而不用暴露密码。
  • env.gateway,定义网关IP, 同命令参数 -g
  • env.roledefs, 定义角色分组,比如web组与db组主机区分开来,定义如下:

    env.roledefs = {
    'webservers': ['192.168.1.21', '192.168.1.22', '192.168.1.23', '192.168.1.24'],
    'dbservers':['192.168.1.25', '192.168.1.26']
    }
    

    引用时使用Python修饰符的形式进行,角色修饰下面的任务函数为其作用域,下面来看一个示例:

@roles('webservers')
def webtask():
    run('/etc/init.d/nginx start')
     

@roles('dbservers')
def dbtask():
    run('/etc/init.d/mysql start')
    
@roles('webservers', 'dbservers')
def pubclitask():
    run('uptime')
    
def deploy():
    execute(webtask)
    execute(dbtask)
    execute(pubclitask)

在命令行执行fab deploy就可以实现不同角色执行不同的任务函数了。

常用API

这些API封装了执行本地命令,执行远程主机命令等功能。
说明如下:

  • local ,执行本地命令。 如:local(‘uname -s’);
  • run, 执行远程命令
  • lcd, 切换本地目录,
  • cd ,切换远程目录。
  • sudo ,sudo 方式执行远程命令
  • put 上传本地文件到远程主机
  • get 从远程主机下载文件到本地
  • prompt,获取用户输入信息,用于交互
  • confirm, 获得提示信息确认,用于交互
  • reboot, 重启远程主机
  • @task, 函数修饰符,标识的函数为fab可调用的,非标记对fab不可见,纯业务逻辑;
  • @runs_once, 函数修饰符,标识的函数只会执行一次,不受多台主机影响。

后记

更细节的可以考虑官网
示例可以看刘天斯写的<Python自动化运维>或廖雪峰的Python教程。

SQLAlchemy介绍

前言

玩Python的人很有必要非常熟悉SQLAlchemy。因为它是python中最主流的orm。
我之前只在flask中用过。发现用的还不是很顺畅,不能手到拿来。故又整理了这篇文章。

查询sql有几个点:

  1. 直接原始语句查询。
  2. 对象关系映射,即orm
  3. 其它关联的是数据库链接池和事务。

下面一一道来。

直接使用原生语句查询

pymysql

SQLAlchemy依赖于各种驱动,底层其实还是用的pymysql之类的。相当于一个适配器类,把其它的操作都抽象化了。

查询示例

import  pymysql
 
#创建连接
conn = pymysql.connect(host='192.168.56.11',port=3306,user='root',passwd='root',db='oldboydb')
#创建游标  socket上建立的实例
cursor=conn.cursor()
  
#执行SQL,并返回行数,用游标执行,
effect_row = cursor.execute("select * from student")
# print(cursor.fetchone())
# print(cursor.fetchone())
print(cursor.fetchall())

插入示例

import  pymysql

#创建连接
conn = pymysql.connect(host='192.168.56.11',port=3306,user='root',passwd='root',db='oldboydb')
#创建游标  socket上建立的实例
cursor=conn.cursor()
data = [
    ("N1","2015-05-22",'M'),
    ("N2","2015-05-22",'M'),
    ("N3","2015-05-22",'M'),
    ("N4","2015-05-22",'M'),
    ]
cursor.executemany("insert into student (name,register_date,gender) values(%s,%s,%s)",data )
conn.commit()

使用SQLAlchemy

这个是SQLAlchemy Core中的。

查询

from sqlalchemy import create_engine
e = create_engine('mysql://user:pass@host/db')
for row in e.execute('select * from table where id < %s', 2):
    print(dict(row))

这是最简单的,只用到了engine对象。

还可以用字典参数,如下

from sqlalchemy import text
result = e.execute(text('select * from table where id < :id'), {'id': 2})

相对于上面pymysql中只能用索引或字典。
这里可以用索引、key、属性。

row[0] == row['id'] == row.id

事务支持

conn = e.connect()
try:
    conn.begin()
    #dosomething
    conn.commit()
except:
    conn.rollback()

python版本的sql表达式

这个比写原生sql语句好,因为可以跨数据库引擎写。我就不知道sqlserver,但工作中有这种类型的库。
我用python就比较开心了。不用每次都上网查。
这个就是我需要用的,临时任务写orm太复杂了, 偏偏又不熟悉sqlserver。

查询

from sqlalchemy import Table, MetaData
meta = MetaData(bind=e, reflect=True)
users = meta.tables['user]
list(e.execute(users.select(table.c.id < 2)))

除了上面的直接在engine上查询,也可以在connection上查询

con  = engine.connect()
con.execute(users.insert(), name='admin', email='admin@loclhost')

甚至还可以直接在table上调用excute()方法

users.select(users.c.id == 1).execute().first()

ORM

先看一个示例,半手动

from sqlalchemy import orm
class Table(object):
    pass

meta = MetaData(bind=e, reflect=True) 
orm.Mapper(Table, meta.tables['table'])
s = orm.Session(bind=e)
s.query(Table).filter(Table.id < 2).first().info

注意到几个对象:
engine, 数据库连接的. 可以直接在engine上查询。
connection, 这个是和事务相关的。 当用connection时,查询是在connection上。
MetaData, 对应数据库表的,可以手写Table, 也可以自动反射出来。
Mapper对象就是用来把object和table 做映射的。
session 这里其实已经把事务加了进来, 查询是在session上。原如的sql和python表达式都是在engin对象上。
在flask-sqlalchemy中,查询是直接在对象上的。

声明的方式

上面用的是半手动模式,object是手动的,table是自动反射的。
这里介绍声明的方式

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
# 创建实例,并连接test库
engine = create_engine("mysql+pymysql://root:123456@localhost/test",
                                    encoding='utf-8', echo=True)
# echo=True 显示信息
Base = declarative_base()  # 生成orm基类
                                    
class User(Base):
    __tablename__ = 'user'  # 表名,这里就关联上Table了
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    password = Column(String(64))
                                                    
Base.metadata.create_all(engine) #创建表结构 (这里是父类调子类)

手动模式

from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
from sqlalchemy.orm import mapper
metadata = MetaData()
user = Table('user', metadata,
            Column('id', Integer, primary_key=True),
            Column('name', String(50)),
            Column('fullname', String(50)),
            Column('password', String(12)))

class User(object):
    def __init__(self, name, fullname, password):
        self.name = name
        self.fullname = fullname
        self.password = password

mapper(User, user)

另一种半手动

上面的方式user表是手动写的。还可以用autoload自动配置。

user = Table('user', metadata, autoload=True)

使用reflect性能会比较低,他会一次性把整个库的所有表都看下结构,然后自动配置。
autoload只会自动反射当前表。
性能最佳的当然还是手动模式。

查询

Session_class = sessionmaker(bind=engine)  # 实例和engine绑定
Session = Session_class()  # 生成session实例,相当于游标
my_user = Session.query(User).filter_by(name="fgf").first()  # 查询
print(my_user)

插入

# 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
Session_class = sessionmaker(bind=engine)  # 实例和engine绑定
Session = Session_class()  # 生成session实例,相当于游标

user_obj = User(id=27,name="fgf",password="123456")  # 生成你要创建的数据对象
print(user_obj.name,user_obj.id)  # 此时还没创建对象呢,不信你打印一下id发现还是None

Session.add(user_obj)  # 把要创建的数据对象添加到这个session里, 一会统一创建
print(user_obj.name,user_obj.id) #此时也依然还没创建

Session.commit() #现此才统一提交,创建数据

遇到的问题

连接池的问题

现在开始流行serverless了,这种模式下建议是关闭连接池。
关闭的方法是在创建engin时指定连接池类为NullPoll类.

e = create_engine('mssql+pymssql://yourserver',
                  poolclass=pool.NullPool)

orm类型找不到问题

参考
https://stackoverflow.com/questions/34894170/difficulty-serializing-geography-column-type-using-sqlalchemy-marshmallow

分表问题

通过type类自动生成对应的类。

其它经验

sqlacodegen

sqlacodegen是orm中model的自动生成工具。有了这个工具,你就不用手写model对象了。

参考

http://www.mapfish.org/doc/tutorials/sqlalchemy.html
http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html
http://blog.csdn.net/tantexian/article/details/39230459
http://docs.sqlalchemy.org/en/latest/

Python概览

Python概览

print("Hello, Welcome to Python's world")

欢迎进入Python的世界,第一件事请习惯,我们不用{}, 我们用缩进。
用缩进的请注意,空格和tab不能混用。 注意到了这个,你就能避免下面的错误

IndentationError: unexpected indent

推荐的项目结构

作者开发了知名的flask轻量级web框架和requests库。

git仓库

python代码组织结构
package/module/变量。
package是指带有__init__.py 的目录, 当被首次被import和reload 的时候__init__.py 会执行,

包安装 pip工具

pip install package
pip freeze > requestments.txt
pip install -r requestments.txt

一般是和virtualenv结合起来用的。

解决pip安装慢

多版本管理pyenv

pyenv vertions 列出当前安装的版本
pyenv install version 安装指定的版本
pyenv global version 设置全局的python版本
Python 多版本共存之 pyenv

干净的应用环境virtualenv

virtualenv venv
virtualenv venv -p 指定python版本
source venv/bin/active
deactive
Python虚拟环境virtualenv

代码风格

PEP8 标准

pycodestyle 检测是否符合标准
pycodestyle yourscript.py
autopep8 可以自动替换成符合标准的格式
autopep8 --in-place yourscript.py

单元测试

  1. nose包, 安装后有nosetests命令 nosetests -v
  2. unittest python -m unittest module_name
  3. doctest 这个是更多是用在演示api如何使用的。 也可能通过doctest模块运行,如果文档的值和实际的值不一样,就会报错误。
  4. pytest unittest的可替代品
  5. tox 在需要多版本兼容时,可以用tox做自动化测试
  6. mock Python单元测试 #效率问题 Python专题之性能与优化

自动文档化 Sphinx

应用介绍

web方向

Django
Flask
Tornado
Pyramid
Twisted

运维方向

fabric
运维管理工具fabric详解
ansible
puppet

大数据方向

机器学习方向

推荐学习

  1. 入门级 可以廖雪峰的教程。
  2. 深入语法 可以学<Python学习手册>。
  3. 整体感知可以看下<Python高手之路>.
  4. web开发可以学

比较好用的库推荐

运维管理 psutils

黑客攻防

ORM SQLAlchemy

SQLAlchemy

requests 库, http请求库

Python3标准库urllib vs requests

logging模块,标准日志

python之logging模块

建议掌握好的几个概念

装饰器

def foo():
    # do something

def decorator(func):
    # manipulate func
    return func
    
foo = decorator(foo) #手动装饰

@decorator
def bar():
    # Do someting
    # bar() is decorated

上下文管理 context manager

函数式编程

Python函数式编程

标准库

下面是一些必须了解的标准库模块。

  • abc 提供抽象基类等功能。
  • atexit 允许注册在程序退出时调用的函数
  • argparse 提供解析命令行参数的函数。
  • bisect 为可排序列表提供二分查找算法。
  • calendar 提供一组与日期相关的函数。
  • codecs 提供编解码数据的函数。
  • collections 提供一组有用的数据结构。
  • copy 提供复制数据的函数。
  • csv 提供读写CSV文件的函数。
  • datetime 提供用于处理日期和时间的类。
  • fnmatch 提供用于匹配Unix风格文件名模式的函数。
  • glob 提供用于匹配Unix风格路径模式的函数。
  • io 提供用于处理I/O流的函数。
  • json 提供用来读写JSON格式函数的函数。
  • logging 提供对Python内置的日志功能的访问。可以参考这里
  • multiprocessing 可以在应用程序中运行多个子进程。可以参考这里
  • operator 提供实现基本的Python运算符功能的函数,可以使用这些函数而不是自己写lambda表达式。
  • os 提供对基本的操作系统函数的访问。
  • random 提供生成伪随机数的函数。。不能用在安全领域。
  • re 提供正则表达式功能。
  • select 提供对函数select()和poll()的访问,用于创建事件循环。
  • shutil 提供对高级文件处理函数的访问。
  • signal 提供用于处理POSIX信号的函数。可以参考这里
  • tempfile 提供用于创建临时文件和目录的函数。可以参考这里
  • threading 提供对处理高级线程功能的访问。可以参考这里
  • urllib(以及Python2.x中的urllib2和urlparse)提供处理和解析URL的函数。
  • uuid可以生成全局唯一标识符。

Linux磁盘分区及链接文件的特点-演道网

Linux系统分区

传统的分区fdisk 最大支持2T的硬盘分区

对存储,多分区使用的parted

  • 主分区:最多只能有4个
  • 扩展分区
    • 最多只能有1个
    • 主分区加扩展分区最多有4个
    • 不能写入数据,只能包含逻辑分区
  • 逻辑分区

在Linux中,任何东西都是文件

挂载

  • 必须分区
    • / (根分区)
    • swap分区(交换分区,4G以下,内存两倍,4G以上,内存一样)
  • 推荐分区
    • /boot 启动分区,200MB

fdisk  /dev/sda  ###sdx 都是ISCSI

参数:

  a  toggle a bootable flag
  b  edit bsd disklabel
  c  toggle the dos compatibility flag
  d  delete a partition                              ###删除分区
  l  list known partition types                    ###列分区id信息,82/83
  m  print this menu
  n  add a new partition           ###添加分区
  o  create a new empty DOS partition table
   p  print the partition table                      ###打印分区表
  q  quit without saving changes
  s  create a new empty Sun disklabel
   t  change a partition’s system id     ###修改分区id 82 swap  83默认linux
  u  change display/entry units
  v  verify the partition table
  w  write table to disk and exit      ###保存退出磁盘
  x  extra functionality (experts only)

02、格式化

mkfs.ext4 | xfs |ext3  /dev/sdx 

03、挂载分区

mount  /dev/sdx  /data 

/etc/fstab  ###开机自动挂载

/dev/sdx  /data  ext4  defaults  1 1

mount  -l              ###查看本地挂载信息

mount | column -t ###查看所有挂载信息【多用于排查远程挂载,服务端关闭引起的问题】


ln -s [原文件] [目标文件]
-s
创建软链接

-f 强制建立链接

ln -sf source target

ln    source target    ###硬链接

硬链接特征:
1.
拥有相同的iNode和存储block,可以看做是同一个文件
2.
可通过iNode识别 相同inode
3.
不能跨分区
4.
不能针对目录使用,只能针对文件

软链接特征:
1.
类似windows快捷方式
2.
软链接拥有自己的iNodeblock块,但是数据块中只保存原文件的文件名和iNode,并没有实际的文件数据
3.
lrwxrwxrwx l软链接,文件权限都为全rwx
4.
修改任意文件,另一个都改变
5.
删除原文件,软链接不能使用

转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn

GitHub 协作冲突原因及解决方法-演道网

GitHub协作冲突出现的原因,是两个人同时修改代码,一个人先提交,后提交的人就会被拒绝rejected

 

 输入 git pull origin master

出现merging

进入文件看到出现冲突信息

 

进行修改,保存

重新提交add commit push 

另一个用户进行pull,冲突解决

 

GitHub 教程系列文章: 

通过GitHub创建个人技术博客图文详解  http://www.linuxidc.com/Linux/2015-02/114121.htm

GitHub 使用教程图文详解  http://www.linuxidc.com/Linux/2014-09/106230.htm 

使用 GitHub / GitLab 的 Webhooks 进行网站自动化部署  http://www.linuxidc.com/Linux/2016-06/131993.htm

多个GitHub帐号的SSH key切换 http://www.linuxidc.com/Linux/2016-05/131080.htm

如何在同一台电脑上使用两个GitHub账户 http://www.linuxidc.com/Linux/2016-05/131079.htm

利用GitHub搭建个人Maven仓库  http://www.linuxidc.com/Linux/2016-04/130197.htm

一分钟认识GitHub http://www.linuxidc.com/Linux/2015-11/125089.htm

分享实用的GitHub 使用教程 http://www.linuxidc.com/Linux/2014-04/100556.htm 

GitHub使用操作指南  http://www.linuxidc.com/Linux/2016-10/135782.htm

GitHub 的详细介绍请点这里
GitHub 的下载地址请点这里

转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn

在Ubuntu环境下安装OctoMap-演道网

由于工程实践中需要对机器人地图进行概率化估计并表示,故引入OctoMap库。本文将介绍如何在Ubuntu环境下安装OctoMap。

    1 OctoMap的下载:

    使用git从github下载OctoMap库。

git clone https://github.com/OctoMap/octomap

     如果系统没有安装git则输入以下指令安装git:

sudo apt-get install git

    如果使用git下载OctoMap连接不上,而使用ubuntu自带的浏览器速度又很慢,推荐使用chormium去官网直接下载。 

    输入如下指令安装chormium:

sudo add-apt-repository ppa:a-v-shkop/chromium
sudo apt-get update
sudo apt-get install chromium

    2 编译环境的安装

    由于初期调试的不顺利,尝试了多个版本的ubuntu。推荐使用ubuntu16.04 32bit版本 ,当然选用老版的也都可以,我选择的版本是ubuntu 16.04 32bit 和ubuntu 14.04 32bit。

    OctoMap的编译依赖于以下几个库,输入如下指令对其进行安装。

sudo apt-get install build-essential cmake doxygen libqt4-dev 
libqt4
-opengl-dev libqglviewer-qt4-dev

    若选择Ubuntu 16.04版本则将“libqglviewer-qt4-dev”换成“libqglviewer-dev-qt4”,若为Ubuntu 14.04版本则将“libqglviewer-qt4-dev”换成”libqglviewer-dev” 。

    请对所有编译环境进行安装,尽管在部分库缺失的情况下编译也能够成功,但实际运行时程序将会报错,故老老实实的把所有库都给安装上去吧。

    安装完依赖库之后进入OctoMap的文件夹中,输入如下指令对其进行编译。

cd octomap
mkdir build
cd build
cmake ..
make

3 OctoMap中Octovis的使用 

    编译完成接下来尝试一下OctoMap的图形显示功能,输入:

bin/octovis octomap/share/data/geb079.bt

   可以看到一张基本的地图。如下是使用octovis用不同分辨率显示实验室环境的激光雷达数据。

 

转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn