miniblast_hash算法c语言实现
对于一组基因文件中的基因序列,选取一段基因片段,作为索引,利用hash表,查找固定的基因片段。有一定的并且容忍错误。
简单讲就是自己实现一个hashtable,将选出特定字符串建立索引,便于查询。输出时可容忍一定数量的错误。
贴上代码
HashTable.h
#include <iostream>
using namespace std; typedef int KeyType; #define NULLKEY -1 struct Entry {
KeyType _key;
string _value;
Entry(KeyType key = NULLKEY, string value = "") :_key(key), _value(value) {}
}; class hashTable {
public:
hashTable();
hashTable::hashTable(int table_size, double occupancy_get);
//hashTable(int tableSize);
~hashTable(); bool find(const Entry& e);
string hashTable::getValue(const KeyType& k);
bool insert(const Entry& e);
bool remove(const Entry& e);
void clear();
Entry& operator[](KeyType key);//重载下标操作;当找不到key对应的Entry时,插入Entry(key,0)
int size();
void display(); protected:
int hashFunction(KeyType key);//将键值映射到对应地址
void rehash();//调整hashTable大小
bool find(const KeyType& k);//按键值查找
int nextPrime();//p(n) = n^2 - n + 41, n<41, p<1681 private:
Entry *_pTable;
int _pos;//当前访问元素的位置
int _size;
int _capacity;
int primeIndex;
};
HashTable.cpp
#include "HashTable.h"
static double _occupancy = 0.5;
//开放定址法
hashTable::hashTable()
{
_capacity = ;//初始化hashTable容量为100,便于观察rehash过程
_pTable = new Entry[_capacity];
_size = ;
primeIndex = ;
}
hashTable::hashTable(int table_size,double occupancy_get)
{
_capacity = table_size;
_occupancy = occupancy_get;
_pTable = new Entry[_capacity];
_size = ;
primeIndex = ;
} hashTable::~hashTable()
{
clear();
} int hashTable::nextPrime()
{
int p = std::pow(static_cast<float>(primeIndex), ) - primeIndex +;
primeIndex = primeIndex << ;
if (primeIndex >= ) {
cout << "Max capacity reached. exit!" << endl;
exit(-);
}
return p;
} bool hashTable::find(const Entry& e)
{
return(find(e._key));
} bool hashTable::find(const KeyType& k)
{
_pos = hashFunction(k);
if (_pTable[_pos]._key == NULLKEY)
return false;
int lastPos = _pos;
while (_pTable[_pos]._key != k) {
if (++_pos%_capacity == lastPos)
return false;
}
return true;
} string hashTable::getValue(const KeyType& k)
{
_pos = hashFunction(k);
if (_pTable[_pos]._key == NULLKEY)
return "";
int lastPos = _pos;
while (_pTable[_pos]._key != k) {
if (++_pos%_capacity == lastPos)
return "";
}
return _pTable[_pos]._value;
} bool hashTable::insert(const Entry& e)
{
if ((_size*1.0) / _capacity>_occupancy) //通过occupancy判断是否需要扩容
rehash();//[OK]插入操作前,需要判断hash table是否需要扩容
if (find(e))
return false;
_pTable[_pos] = e;
++_size;
return true;
} bool hashTable::remove(const Entry& e)
{
if (!find(e))
return false;
_pTable[_pos]._key = NULLKEY;
--_size;
//rehash();//移除操作后,需要判断hash table是否需要缩容
return true;
} void hashTable::clear()
{
delete[]_pTable;
_size = _capacity = ;
} Entry& hashTable::operator[](KeyType key)
{
if (!find(key))
insert(Entry(key, ));
return _pTable[_pos];
} int hashTable::size()
{
return _size;
} int hashTable::hashFunction(KeyType key)
{
return key%_capacity;
} void hashTable::display()
{
cout << "capacity = " << _capacity << ", size = " << _size << endl;
for (int i = ; i<_capacity; i++) {
if (_pTable[i]._key != NULLKEY);
// cout << "key=" << _pTable[i]._key << ",value=" << _pTable[i]._value << endl;
}
} void hashTable::rehash()
{
//cout << "begin rehash..." << endl;
Entry *p = new Entry[_size];//用来暂存原哈希表
for (int i = ; i<_capacity; i++) {//i<_size不对;元素散列在容量为_capacity的hashTable中
if (_pTable[i]._key != NULLKEY)
*(p + i) = _pTable[i];
}
delete[]_pTable;
int lastSize = _size;
_size = ; _capacity = nextPrime();
_pTable = new Entry[_capacity];
for (int i = ; i<lastSize; i++)
insert(*(p + i));
delete[]p;
}
miniblast_hash.cpp
#include <iostream>
#include <string>
#include <fstream>
#include "HashTable.h" using namespace std;
const int KMER_MAX = ; //得到基因组文件中,position开始,长度为len的字符串
string getStringByPos(string file_name, long position,int str_len) {
//读入数据
std::ifstream myfile(file_name);
if (!myfile.is_open())
{
cout << "未成功打开文件" << endl;
}
string s = "";
//移动文件指针到基因指定位置,因为有无用字符,需要边移动边判断
for (long i = ; i < position; i++)
{
char c;
myfile.get(c);
//移动指针的过程中要忽略无意义字符
if (c=='/0'||c=='\n')
i--;
}
//截取指定长度的字符串
for (long i = ; i < str_len; i++)
{
char c;
myfile.get(c);
//忽略无意义字符
if (c == '/0' || c == '\n')
i--;
else
{
switch (c)
{
case 'A':
s.append("A");
break;
case 'G':
s.append("G");
break;
case 'C':
s.append("C");
break;
case 'T':
s.append("T");
break;
default:
break;
}
}
}
return s;
}
//比较检索基因片段与原始片段相差个数
int compareString(string s1, string s2, int len) {
int num = ;
for (int i = ; i < len; i++)
{
if (s1[i] != s2[i])
num++;
}
return num;
}
//搜索指定基因片段
void searchGenome(string file_name,hashTable *pTable,int mistakeNum,int kmer,string query_string,string out_name) {
char *kmer_cut = new char[kmer];
int length = query_string.length();
int findNum = ;
int table_size = pTable->size();
//std::ofstream out(out_name, ios::app);//输出结果至文件
for (int i = ; i <kmer; i++)
{
kmer_cut[i] = query_string[i];
}
string kmer_string(&kmer_cut[],&kmer_cut[kmer]);
for (int i = ; i <table_size; i++) { string get = pTable->getValue(i);
if (kmer_string == get)
{ if (i + length > table_size)
continue;
string ss = getStringByPos(file_name, i, length);
int num = compareString(ss, query_string,length);
if (num<=mistakeNum)
{
findNum++;
cout <<i<<" "<<num<<" "<<ss << endl;
// out << i <<" "<< num <<" " << ss << endl;
}
}
} if (findNum==)
{
cout<< "No Match" << endl;
// out << "No Match" << endl;
}
//out.close();
}
//构建基因搜索用的hashtable索引
void GenomeIndex(string genome_file_name,int kmer, hashTable *pTable) {
//读入数据,建立索引
std::ifstream myfile(genome_file_name);
if (!myfile.is_open())
{
cout << "未成功打开文件" << endl;
}
char *c = new char[KMER_MAX];
myfile.get(c, kmer + );
string add(&c[], &c[kmer]);
int geno_loc = ;
pTable->insert(Entry(, add));
//cout << add << endl;
while (!myfile.eof())
{
char next_char;
myfile.get(next_char);
//去除文件中无用字符
if (next_char != '/0'&&next_char != '\n')
{
for (int i = ; i < kmer; i++)
c[i] = c[i + ]; c[kmer-] = next_char;
string add(&c[], &c[kmer]);
geno_loc++;
pTable->insert(Entry(geno_loc, add));
//cout << add <<geno_loc<< endl;
}
}
myfile.close();
} int main(int argc, char* argv[])
{ /*string input_file_name ="";
string out_file_name = "";
if (argc>1)
{
input_file_name = string(argv[1]);
out_file_name = string(argv[2]);
}*/
//如果不需要命令行参数执行文件,直接赋值input_file_name就好
//input_file_name = "input_small.txt";
std::freopen(argv[], "r", stdin);
std::freopen(argv[], "w", stdout);
//std::ifstream inputfile(input_file_name); hashTable *pTable=new hashTable();
/*if (!inputfile.is_open())
{
cout << "未成功打开文件" << endl;
}*/
//先读取命令文件,设置相关参数,初始值为随意指定,无意义
string str_order = "";
string genome_file_name = "";
int table_size =;
double occupancy =0.4;
int kmer = ;
int mistakeNum = ;
string query_string;
bool isIndex = false;
while (str_order!="quit")
{
cin >> str_order;
if (str_order=="genome")
{
cin >> genome_file_name;
}
else if (str_order == "table_size") {
cin >> table_size;
}
else if (str_order == "occupancy") {
cin >> occupancy;
pTable = new hashTable(table_size, occupancy);
}
else if (str_order == "kmer") {
cin >> kmer;
}
else if (str_order == "query") {
cin >> mistakeNum >> query_string;
//首次进行查询前,要建立索引hashTable
if (!isIndex)
{
isIndex = true;
GenomeIndex(genome_file_name, kmer, pTable);
}
//std::ofstream out(out_file_name,ios::app);//输出结果至文件
/*if (out.is_open())
{
out << "Query: " << query_string <<endl; }*/
cout << "Query: " << query_string << endl;
//out.close();
searchGenome(genome_file_name, pTable, mistakeNum, kmer, query_string, "");
}
} delete pTable;//释放指针,防止内存泄露
//getchar();//暂停程序,观察结果
return ;
}
因为需要,代码上有详细注解,欢迎交流学习。
miniblast_hash算法c语言实现的更多相关文章
- 【转】位置式、增量式PID算法C语言实现
位置式.增量式PID算法C语言实现 芯片:STM32F107VC 编译器:KEIL4 作者:SY 日期:2017-9-21 15:29:19 概述 PID 算法是一种工控领域常见的控制算法,用于闭环反 ...
- PID算法(C语言)
/************ PID算法(C语言) ************/ #include <stdio.h> #include<math.h> struct _pid { ...
- PageRank算法R语言实现
PageRank算法R语言实现 Google搜索,早已成为我每天必用的工具,无数次惊叹它搜索结果的准确性.同时,我也在做Google的SEO,推广自己的博客.经过几个月尝试,我的博客PR到2了,外链也 ...
- 数据挖掘算法R语言实现之决策树
数据挖掘算法R语言实现之决策树 最近,看到很多朋友问我如何用数据挖掘算法R语言实现之决策树,想要了解这方面的内容如下: > library("party")导入数据包 > ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...
- 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作
一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...
- 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表
一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...
- 回溯算法-C#语言解决八皇后问题的写法与优化
结合问题说方案,首先先说问题: 八皇后问题:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 嗯,这个问题已经被使用各种语言解 ...
随机推荐
- sizeof数组名和字符指针是有区别的
sizeof数组名和字符指针是有区别的. #include <stdio.h> #include <stdlib.h> void change(char url[]); int ...
- spring data 自定义接口
1 spring data jpa 虽然说spring data 提供了很多DAO 接口,但是依然可能不能满足我们日常的使用,所以,有时我们需要自定义接口方法.自定义接口方法步骤如下: 1. 创建自 ...
- Java reflect 反射 1
1 反射的概述 反射含义:可以获取正在运行的Java对象. JAVA反射机制是在运行状态中,对于任意一个类,都能够得到这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法; 这种动态 ...
- FocusBI:租房分析&星型模型
微信公众号:FocusBI关注可了解更多的商业智能.数据仓库.数据库开发.爬虫知识及沪深股市数据推送.问题或建议,请关注公众号发送消息留言;如果你觉得FocusBI对你有帮助,欢迎转发朋友圈或在文章末 ...
- 人脸识别(基于Caffe)
人脸识别(基于Caffe, 来自tyd) 人脸识别(判断是否为人脸) LMDB(数据库, 为Caffe支持的分类数据源) mkdir face_detect cd face_detect mkdir ...
- 吴恩达《深度学习》第四门课(3)目标检测(Object detection)
3.1目标定位 (1)案例1:在构建自动驾驶时,需要定位出照片中的行人.汽车.摩托车和背景,即四个类别.可以设置这样的输出,首先第一个元素pc=1表示有要定位的物体,那么用另外四个输出元素表示定位框的 ...
- Label控件
文本控件包含标签控件(label).按钮控件(button).文本框控件(textBox)和有格式文本控件(richtextBox) Label控件可以说是最简单的控件,是System.windo ...
- Spring.Net---4、IoC/DI注入方式
spring.net里实现了控制反转IOC(Inversion of control),也即依赖注入DI(Dependency Injection),以达到解耦的目的,实现模块的组件化.程序在调用sp ...
- Java - 使可访问性最小化
模块设计是否良好,有个重要的因素在于,相对外部模块是否隐藏内部数据以及实现细节. 设计良好的模块会隐藏实现细节,并将API与其实现隔离开来. 模块之间通过API进行通信,对于内部工作情况互不可见. 即 ...
- 从MySQL到ORM(二):MySQL基础
一.基本概念 1.数据库: 数据库(DataBase)就是一个存储数据的仓库,为了方便数据的存储和管理,它将数据按照特定的规律存储在磁盘上.通过数据库管理系统,可以有效的组织和管理存储在数据库中的数据 ...