对于一组基因文件中的基因序列,选取一段基因片段,作为索引,利用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语言实现的更多相关文章

  1. 【转】位置式、增量式PID算法C语言实现

    位置式.增量式PID算法C语言实现 芯片:STM32F107VC 编译器:KEIL4 作者:SY 日期:2017-9-21 15:29:19 概述 PID 算法是一种工控领域常见的控制算法,用于闭环反 ...

  2. PID算法(C语言)

    /************ PID算法(C语言) ************/ #include <stdio.h> #include<math.h> struct _pid { ...

  3. PageRank算法R语言实现

    PageRank算法R语言实现 Google搜索,早已成为我每天必用的工具,无数次惊叹它搜索结果的准确性.同时,我也在做Google的SEO,推广自己的博客.经过几个月尝试,我的博客PR到2了,外链也 ...

  4. 数据挖掘算法R语言实现之决策树

    数据挖掘算法R语言实现之决策树 最近,看到很多朋友问我如何用数据挖掘算法R语言实现之决策树,想要了解这方面的内容如下: > library("party")导入数据包 > ...

  5. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  6. 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

    一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...

  7. 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作

    一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...

  8. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

  9. 回溯算法-C#语言解决八皇后问题的写法与优化

    结合问题说方案,首先先说问题: 八皇后问题:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 嗯,这个问题已经被使用各种语言解 ...

随机推荐

  1. InnoDB的分区表

    分区功能并不是在存储引擎层完成的,因此不只有InnoDB存储引擎支持分区,常见的存储引擎MyISAM.NDB等都支持.但也并不是所有的存储引擎都支持,如CSV.FEDERATED.MERGE等就不支持 ...

  2. json test

    public static void main(String[] args) { class B { String name; public String getName() { return nam ...

  3. js处理json数据,java处理json数据

    一.js处理json数据 处理办法之一是把本机json数据或远程返回json数据用eval函数,使之变成DOM对象. 例如: var people = { "programmers" ...

  4. Jenkins 中创建项目时没有Maven项目怎么办

    如果在创建项目时候,没有“创建一个Maven 项目”的选项. 你需要安装Maven项目插件:Maven Integration plugin . 点击“可选插件”  然后在右边的过滤输入框中输入搜索关 ...

  5. 通配符证书导致 Outlook Anywhere 的客户端连接问题

    通配符证书导致 Outlook Anywhere 的客户端连接问题 本主题介绍当您使用 Outlook Anywhere 连接到 Microsoft Exchange 及在组织中跨 Exchange ...

  6. Visual Studio 2017 远程调试(Remote Debugger)应用

    I.远程调试情景 项目部署在远程服务器或非本地环境中,需要 处理应用中遇到的一些错误时 (不能直接附加进程或F5调试应用). II. 远程调试准备 1.远程服务器--操作系统和硬件要求 MSDN 操作 ...

  7. 每天一道剑指offer-二叉树的下一个结点

    题目 每天一道剑指offer-二叉树的下一个结点 https://www.nowcoder.com/practice/ef068f602dde4d28aab2b210e859150a?tpId=13& ...

  8. docker 常见操作

    docker rm $(docker ps -a -q --filter status=exited)   // 删除不在运行的 镜像

  9. C#基础笔记(第十二天)

    1.复习里氏转换:1).子类可以赋值给父类(如果有一个方法需要一个父类作为参数,我们可以传第一个子类对象)2).如果父类中装的是子类对象,则可以将这个父类强转为子类对象 is和as判断转换成功失败 P ...

  10. 浅谈.net MVC

    大学毕业对MVC的概念还不是很清晰,总觉得MVC是和三层一样的,是同一级别的架构.其实不然,三层架构是:BLL(业务逻辑层),DAL(数据库访问层),UI(页面显示层),而MVC仅仅是属于三层架构UI ...