几种数据结构的代码实现
1、vector
class DynamicBitset {
private:
int cap_ = 0;
int size_ = 0;
bool* contain_ = nullptr;
public:
void push_back(bool value) {
++size_;
if (size_ <= cap_) {
contain_[size_ - 1] = value;
}
else {
bool *temp = new bool[2 * size_];
cap_ = 2 * size_;
memcpy(temp, contain_, size_);
temp[size_-1] = value;
if (contain_) {
delete[] contain_;
}
contain_ = temp;
}
}
void pop_bcak(){
if (size_ > 0) {
--size_;
}
}
size_t size()const {
return size_;
}
bool operator[](size_t pos) {
return contain_[pos];
}
};
2、循环队列
//_back是最先插入的,_front是最后插入的位置
template <typename T>
class SqQueue {
public:
SqQueue(int cap) : sz(0), _front(0), _back(0), capacity(cap),
data(std::vector<T>(capacity)) {}
void push(T a) {
if (sz == capacity) {
_back = (_back + 1) % capacity;
data[_front] = a;
_front = (_front + 1) % capacity;
}
else {
data[_front] = a;
_front = (_front + 1) % capacity;
++sz;
}
}
void pop() {
if (sz==0) return;
_back = (_back + 1) % capacity;
--sz;
}
int size() const {
return sz;
}
bool empty() const {
return sz == 0;
}
int back() const {
if (sz == 0) return -1;
return data[_back];
}
private:
int capacity;
int sz;
int _front;
int _back;
std::vector<T> data;
};
3、堆(小顶和大顶)
优先队列(priority queue)可以在 O(1) 时间内获得最大值,并且可以在 O(log n) 时间内取出 最大值或插入任意值。
优先队列常常用堆(heap)来实现。堆是一个完全二叉树,其每个节点的值总是大于等于子 节点的值。实际实现堆时,我们通常用一个数组而不是用指针建立一个树。这是因为堆是完全二叉树,所以用数组表示时,位置 i 的节点的父节点位置一定为 i/2,而它的两个子节点的位置又一 定分别为 2i 和 2i+1。 (这里是按照从1开始,所以代码中需要处理,+1和-1)
以下是堆的实现方法,其中最核心的两个操作是上浮和下沉:如果一个节点比父节点大,那 么需要交换这个两个节点;交换后还可能比它新的父节点大,因此需要不断地进行比较和交换操 作,我们称之为上浮;类似地,如果一个节点比父节小,也需要不断地向下进行比较和交换操作, 我们称之为下沉。如果一个节点有两个子节点,我们总是交换最大的子节点。
通过将算法中的大于号和小于号互换,我们也可以得到一个快速获得最小值的优先队列
class Heap {
std::vector<int> heap;
public:
void output() {
for (const auto& iter : heap) {
std::cout << iter << " ";
}
}
// 获得最大值
int top() {
return heap[0];
}
// 插入任意值:把新的数字放在最后一位,然后上浮
void push(int k) {
heap.push_back(k);
swim(heap.size() - 1);
}
// 删除最大值:把最后一个数字挪到开头,然后下沉
void pop() {
heap[0] = heap.back();
heap.pop_back();
sink(0);
}
// 上浮
void swim(int pos) {
++pos;
while (pos > 1 && heap[pos / 2 - 1] < heap[pos - 1]) {
std::swap(heap[pos / 2 - 1 ], heap[pos-1]);
pos /= 2;
}
}
// 下沉
void sink(int pos) {
++pos;
while (2 * pos <= heap.size()) {
int i = 2 * pos;
if (i < heap.size() && heap[i-1] < heap[i]) ++i;
if (heap[pos-1] >= heap[i-1]) break;
std::swap(heap[pos-1], heap[i-1]);
pos = i;
}
}
};
4、hash表
#include<bits/stdc++.h>
template <typename T>
class HashTable {
private:
vector<list<T>> hash_table;
// 哈希函数
int myhash(const T & obj) const {
return hash(obj, hash_table.size());
}
public:
// size最好是质数
HashTable(int size = 31) {
hash_table.reserve(size);
hash_table.resize(size);
}
~HashTable() {}
// 查找哈希表是否存在该值
bool contains(const T & obj) {
int hash_value = myhash(obj);
const list<T> & slot = hash_table[hash_value];
std::list<T>::const_iterator it = slot.cbegin();
for (; it != slot.cend() && *it != obj; ++it);
return it != slot.cend();
}
// 插入值
bool insert(const T & obj) {
if (contains(obj)) {
return false; 11.7 哈希表 – 95 / 143 –
}
int hash_value = myhash(obj);
std::list<T> & slot = hash_table[hash_value];
slot.push_front(obj);
return true;
}
// 删除值
bool remove(const T & obj) {
list<T> & slot = hash_table[myhash(obj)];
auto it = find(slot.begin(), slot.end(), obj);
if (it == slot.end()) {
return false;
}
slot.erase(it);
return true;
}
};
// 一个简单的对整数实现的哈希函数
int hash(const int & key, const int &tableSize) {
return key % tableSize;
}
5、二叉搜索树
template <class T>
class BST {
struct Node {
T data;
Node* left;
Node* right;
};
Node* root;
//释放树所占的内存
Node* makeEmpty(Node* t) {
if (t == NULL) return NULL;
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
return NULL;
}
Node* insert(Node* t, T x) {
if (t == NULL) {
t = new Node;
t->data = x;
t->left = t->right = NULL;
}
else if (x < t->data) {
t->left = insert(t->left, x);
}
else if (x > t->data) {
t->right = insert(t->right, x);
}
return t;
}
Node* find(Node* t, T x) {
if (t == NULL) return NULL;
if (x < t->data) return find(t->left, x);
if (x > t->data) return find(t->right, x);
return t;
}
Node* findMin(Node* t) {
if (t == NULL || t->left == NULL) return t;
return findMin(t->left);
}
Node* findMax(Node* t) {
if (t == NULL || t->right == NULL) return t;
return findMax(t->right);
}
Node* remove(Node* t, T x) {
Node* temp;
if (t == NULL) return NULL;
else if (x < t->data) t->left = remove(t->left, x);
else if (x > t->data) t->right = remove(t->right, x);
else if (t->left && t->right) {
temp = findMin(t->right);
t->data = temp->data;
t->right = remove(t->right, t->data);
}
else {
temp = t;
if (t->left == NULL) t = t->right;
else if (t->right == NULL) t = t->left;
delete temp;
}
return t;
}
public:
BST() : root(NULL) {}
~BST() {
root = makeEmpty(root);
}
void insert(T x) {
insert(root, x);
}
void remove(T x) {
remove(root, x);
}
};
6、字典树
class TrieNode {
public:
TrieNode* childNode[26];
bool isVal;
TrieNode() : isVal(false) {
for (int i = 0; i < 26; ++i) {
childNode[i] = nullptr;
}
}
};
class Trie {
TrieNode* root;
public:
Trie() : root(new TrieNode()) {}
// 向字典树插入一个词
void insert(std::string word) {
TrieNode* temp = root;
for (int i = 0; i < word.size(); ++i) {
if (!temp->childNode[word[i] - 'a']) {
temp->childNode[word[i] - 'a'] = new TrieNode();
}
temp = temp->childNode[word[i] - 'a'];
}
temp->isVal = true;
}
// 判断字典树里是否有一个词
bool search(std::string word) {
TrieNode* temp = root;
for (int i = 0; i < word.size(); ++i) {
if (!temp) {
break;
}
temp = temp->childNode[word[i] - 'a'];
}
return temp ? temp->isVal : false;
}
// 判断字典树是否有一个以词开始的前缀
bool startsWith(std::string prefix) {
TrieNode* temp = root;
for (int i = 0; i < prefix.size(); ++i) {
if (!temp) {
break;
}
temp = temp->childNode[prefix[i] - 'a'];
}
return temp;
}
};
算法
5、字符串匹配
// 主函数
int strStr(std::string haystack, std::string needle) {
int k = -1, n = haystack.length(), p = needle.length();
if (p == 0) return 0;
std::vector<int> next(p, -1); // -1表示不存在相同的最大前缀和后缀12.5 练习 – 109/143 –
calNext(needle, next); // 计算next数组
for (int i = 0; i < n; ++i) {
while (k > -1 && needle[k + 1] != haystack[i]) {
k = next[k]; // 有部分匹配,往前回溯
}
if (needle[k + 1] == haystack[i]) {
++k;
}
if (k == p - 1) {
return i - p + 1; // 说明k移动到needle的最末端,返回相应的位置
}
}
return -1;
}
// 辅函数 - 计算next数组
void calNext(const std::string &needle, std::vector<int> &next) {
for (int j = 1, p = -1; j < needle.length(); ++j) {
while (p > -1 && needle[p + 1] != needle[j]) {
p = next[p]; // 如果下一位不同,往前回溯
}
if (needle[p + 1] == needle[j]) {
++p; // 如果下一位相同,更新相同的最大前缀和最大后缀长
}
next[j] = p;
}
}
6、二叉树的三种遍历方式
void preOrder(TreeNode* root) {
std::stack<TreeNode*> house;
while (!root||!house.empty())
{
if (root) {
std::cout << root->val << std::endl;
house.push(root);
root = root->left;
}
else {
TreeNode* temp = house.top();
house.pop();
root = temp->right;
}
}
}
void inOrder(TreeNode* root) {
if (root == nullptr) return;
std::stack<TreeNode*> house;
while (!house.empty()||!root)
{
while (root)
{
house.push(root);
root = root->left;
}
TreeNode* temp = house.top();
std::cout << temp->val << std::endl;
house.pop();
root = temp->right;
}
}
void postOrder(TreeNode* root) {
if (root == nullptr) return;
std::stack<TreeNode*> house;
TreeNode* pre = nullptr;
house.push(root);
while (!root||!house.empty())
{
TreeNode* cur = house.top();
if ((cur->left == nullptr&&cur->right == nullptr) ||
(pre != nullptr && (pre == cur->left || pre == cur->right))) {
std::cout << cur->val << std::endl;
house.pop();
pre = cur;
}
else {
if (cur->left != nullptr) {
house.push(cur->left);
}
if (cur->right != nullptr) {
house.push(cur->right);
}
}
}
}
7、拓扑排序
typedef struct ArcNode{
int adjvex;
struct ArcNode *nextarc;
ArcNode(){nextarc=NULL;}
}ArcNode;
typedef struct VNode{
int data;
ArcNode *firstarc;
VNode(){firstarc=NULL;}
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertices;
int vexnum,arcnum;
}ALGraph;
bool TopologicalSort(ALGraph G,int *indegree)
{
stack<int> s;
int i,k;
for(i=1;i<G.vexnum+1;i++)
{
if(!indegree[i])
s.push(i);
}
int count=0;
ArcNode *p;
while(!s.empty())
{
i = s.top();
s.pop();
cout<<G.vertices[i].data<<"->";
count++;
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
k = p->adjvex;
indegree[k]--;
if(!indegree[k])
s.push(k);
}
}
if(count<G.vexnum)
return false;
return true;
}
8、快速排序
#include <iostream>
#include <algorithm>
#include <vector>
#include <stdlib.h>
void quickSort(std::vector<int> &q, int l, int r){
if(l >= r)
return;
int i = l - 1, j = r + 1, x = q[l + rand() % (r - l + 1)];
while(i < j){
do j--; while(q[j] > x);
do i++; while(q[i] < x);
if(i < j)
swap(q[i], q[j]);
else{
quickSort(q, l, j);
quickSort(q, j + 1, r);
}
}
}
int main(){
int n;
std::vector<int> q;
cin >> n;
for(int i = 0, t; i < n; i++){
std::cin >> t;
q.push_back(t);
}
quickSort(q, 0, n - 1);
for(auto x : q)
std::cout << x << ' ';
std::cout << endl;
return 0;
}