散列表(Hash表)
实现一个基于链表法解决冲突问题的散列表
typedef struct node //记录对应的节点
{
keytype key;
...
struct noode *next;
}Renode;
Renode *LinkHsearch(Renode *HT[m], keytype k) //链地址法解决冲突时的查找算法
{
Renode *p;
int d;
d = H(k); //求Hash地址并赋值给d
p = HT[d]; //取链表头节点指针
while(p && (p->key != k))
p = p->next; //冲突时取下一同一词节点
return (p); //查找成功时p->key == k,否则p=^
}
void LinkHinsert(Renode *HT[m], Renode *S) //将指针S所指记录插入表HT的算法
{
int d;
Renode *p;
p = LinkHsearch(HT, S->key); //查找S节点
if(p) error(); //记录已存在时的处理
else
{
d = H(S->key);
S->next = HT[d];
HT[d] = S;
}
}
实现一个 LRU 缓存淘汰算法
class LRUCache{
private:
//LRU数据结构
struct Node{
int key;
int value;
Node(int k,int v):key(k),value(v){
}
};
public:
LRUCache(int c):capacity(c) {
}
int get(int key){
if (cacheMap.find(key) == cacheMap.end())
return -1; //这里产生缺页中断,根据页表将页面调入内存,然后set(key, value)
//将key移到第一个,并更新cacheMap
cacheList.splice(cacheList.begin(),cacheList,cacheMap[key]);
cacheMap[key] = cacheList.begin();
return cacheMap[key]->value;
}
void set(int key, int value){
if (cacheMap.find(key) == cacheMap.end())
{
//淘汰最后一个,然后将其加到第一个位置
if (cacheList.size() == capacity)
{
cacheMap.erase(cacheList.back().key);
cacheList.pop_back();
}
cacheList.push_front(Node(key,value));
cacheMap[key] = cacheList.begin();
}
else
{
//更新节点的值,并将其加到第一个位置
cacheMap[key]->value = value;
cacheList.splice(cacheList.begin(),cacheList,cacheMap[key]);
cacheMap[key] = cacheList.begin();
}
}
private:
int capacity;
list<Node> cacheList;
unordered_map<int, list<Node>::iterator> cacheMap;
};
字符串
实现一个字符集,只包含 a~z 这 26 个英文字母的 Trie 树
public class Trie {
private Node root;
private int size;
private static class Node {
public boolean isWord;
public Map<Character, Node> next;
public Node() {
next = new TreeMap<>();
}
public Node(boolean isWord) {
this();
this.isWord = isWord;
}
}
public Trie() {
root = new Node();
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
/** * 插入操作 * * @param word 单词 */
public void add(String word) {
Node current = root;
char[] cs = word.toCharArray();
for (char c : cs) {
Node next = current.next.get(c);
if (next == null) {
current.next.put(c, new Node());
}
current = current.next.get(c);
}
//如果当前的node已经是一个word,则不需要添加
if (!current.isWord) {
size++;
current.isWord = true;
}
}
/** * 是否包含某个单词 * * @param word 单词 * @return 存在返回true,反之false */
public boolean contains(String word) {
Node current = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
Node node = current.next.get(c);
if (node == null) {
return false;
}
current = node;
}
//如果只存在 panda这个词,查询 pan,虽然有这3个字母,但是并不存在该单词
return current.isWord;
}
/** * Trie是否包含某个前缀 * * @param prefix 前缀 * @return */
public boolean containsPrefix(String prefix) {
Node current = root;
for (int i = 0; i < prefix.length(); i++) {
char c = prefix.charAt(i);
Node node = current.next.get(c);
if (node == null) {
return false;
}
current = node;
}
return true;
}
/* * 1,如果单词是另一个单词的前缀,只需要把该word的最后一个节点的isWord的改成false * 2,如果单词的所有字母的都没有多个分支,删除整个单词 * 3,如果单词的除了最后一个字母,其他的字母有多个分支, */
/** * 删除操作 * * @param word * @return */
public boolean remove(String word) {
Node multiChildNode = null;
int multiChildNodeIndex = -1;
Node current = root;
for (int i = 0; i < word.length(); i++) {
Node child = current.next.get(word.charAt(i));
//如果Trie中没有这个单词
if (child == null) {
return false;
}
//当前节点的子节点大于1个
if (child.next.size() > 1) {
multiChildNodeIndex = i;
multiChildNode = child;
}
current = child;
}
//如果单词后面还有子节点
if (current.next.size() > 0) {
if (current.isWord) {
current.isWord = false;
size--;
return true;
}
//不存在该单词,该单词只是前缀
return false;
}
//如果单词的所有字母的都没有多个分支,删除整个单词
if (multiChildNodeIndex == -1) {
root.next.remove(word.charAt(0));
size--;
return true;
}
//如果单词的除了最后一个字母,其他的字母有分支
if (multiChildNodeIndex != word.length() - 1) {
multiChildNode.next.remove(word.charAt(multiChildNodeIndex + 1));
size--;
return true;
}
return false;
}
}
实现朴素的字符串匹配算法
#ifndef STRING_H_
#define STRING_H_
/*朴素算法查找字符串,时间复杂度是O(nm),不需要预处理*/
int naive_search(const char * txt, const char * pat, int offset[])
{
int i, j, n, m, c = 0;
n = strlen(txt);
m = strlen(pat);
for (i = 0; i <= n - m; i++) {
for (j = 0; j < m; j++)
if (pat[j] != txt[i + j])
break;
if (j == m)
offset[c++] = i;
}
return c;
}
#endif