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格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 嗯,这个问题已经被使用各种语言解 ...
随机推荐
- java的IO流,字节流和字符流
java操作文件都是通过流来处理的,(其实其他很多语言也是这样) 第一:java的IO流,分为:输入流 和 输出流(这真是废话,这是从流向的角度来说的) 第二:java的所有IO流,只分为:字节流 和 ...
- Hudson-ci/Using Hudson/Installing Hudson/Installing Hudson RPM--官方文档
< Hudson-ci | Using Hudson | Installing Hudson(Redirected from Hudson-ci/Installing Hudson RPM) ...
- Fork开源项目之通讯框架
项目发布于:https://github.com/HouZhiHouJue/IOCPMSG.看代码前请先看简介.
- 九、双端队列LinkedBlockDeque
一.简介 JDK通过BlockQueue阻塞队列实现了生产者-消费者模式,生产者向队列添加数据,消费者从队列里面消费数据. 但是在有些场景里面,我们是无法区分生产者消费者的,或者说既是生产者,也是消费 ...
- 撩课-Java每天5道面试题第9天
撩课Java+系统架构 视频 点击开始学习 76.XML技术的作用? XML技术用于数据存储. 信息配置. 数据交换三方面. 可以将数据存储在XML中, 通过节点. 元素内容. 属性标示数据内容及关系 ...
- 【SSH网上商城项目实战21】从Demo中看易宝支付的流程
转自: https://blog.csdn.net/eson_15/article/details/51447492 这一节我们先写一个简单点的Demo来测试易宝支付的流程,熟悉这个流程后, ...
- 如何使Wpf浏览器应用程序被完全信任运行
原文地址链接:http://blogs.microsoft.co.il/maxim/2008/03/05/how-to-run-wpf-xbap-as-full-trust-application/ ...
- python中类变量和实例变量
1. 类变量和实例变量 在Python Tutorial中对于类变量和实例变量是这样描述的: Generally speaking, instance variables are for data u ...
- Python之正则表达式模块
正则表达式符号: . ^ $ * + ? {} () | [] .一个点代表一个字符 ^代表开头 $代表结尾 *代表有0到无数个 [0,+00] ?代表有0到1个 [0,1] +代表有1到无 ...
- 【python爬虫】 之 爬取百度首页
刚开始学习爬虫,照着教程手打了一遍,还是蛮有成就感的.使用版本:python2.7 注意:python2的默认编码是ASCII编码而python3默认编码是utf-8 import urllib2 u ...