几种数据结构和算法的代码实现

几种数据结构的代码实现

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;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值