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格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 嗯,这个问题已经被使用各种语言解 ...
随机推荐
- InnoDB的分区表
分区功能并不是在存储引擎层完成的,因此不只有InnoDB存储引擎支持分区,常见的存储引擎MyISAM.NDB等都支持.但也并不是所有的存储引擎都支持,如CSV.FEDERATED.MERGE等就不支持 ...
- json test
public static void main(String[] args) { class B { String name; public String getName() { return nam ...
- js处理json数据,java处理json数据
一.js处理json数据 处理办法之一是把本机json数据或远程返回json数据用eval函数,使之变成DOM对象. 例如: var people = { "programmers" ...
- Jenkins 中创建项目时没有Maven项目怎么办
如果在创建项目时候,没有“创建一个Maven 项目”的选项. 你需要安装Maven项目插件:Maven Integration plugin . 点击“可选插件” 然后在右边的过滤输入框中输入搜索关 ...
- 通配符证书导致 Outlook Anywhere 的客户端连接问题
通配符证书导致 Outlook Anywhere 的客户端连接问题 本主题介绍当您使用 Outlook Anywhere 连接到 Microsoft Exchange 及在组织中跨 Exchange ...
- Visual Studio 2017 远程调试(Remote Debugger)应用
I.远程调试情景 项目部署在远程服务器或非本地环境中,需要 处理应用中遇到的一些错误时 (不能直接附加进程或F5调试应用). II. 远程调试准备 1.远程服务器--操作系统和硬件要求 MSDN 操作 ...
- 每天一道剑指offer-二叉树的下一个结点
题目 每天一道剑指offer-二叉树的下一个结点 https://www.nowcoder.com/practice/ef068f602dde4d28aab2b210e859150a?tpId=13& ...
- docker 常见操作
docker rm $(docker ps -a -q --filter status=exited) // 删除不在运行的 镜像
- C#基础笔记(第十二天)
1.复习里氏转换:1).子类可以赋值给父类(如果有一个方法需要一个父类作为参数,我们可以传第一个子类对象)2).如果父类中装的是子类对象,则可以将这个父类强转为子类对象 is和as判断转换成功失败 P ...
- 浅谈.net MVC
大学毕业对MVC的概念还不是很清晰,总觉得MVC是和三层一样的,是同一级别的架构.其实不然,三层架构是:BLL(业务逻辑层),DAL(数据库访问层),UI(页面显示层),而MVC仅仅是属于三层架构UI ...