大话数据结构中哈夫曼编码、图论算法的C++实现

最近在读《大话数据结构》,周末闲下来就把书里的哈夫曼编码、求最小生成树的Prim、Kruskal以及求最短路的Dijkstra算法都实现了一遍,也顺便复习了一下优先队列的使用,代码可能不是很优雅欢迎指正!

Huffman

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<queue>
using namespace std;

struct TreeNode
{
    char letter;
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(char c, int v) : letter(c), val(v), left(NULL), right(NULL){}
};
struct cmp
{
    bool operator()(const TreeNode* a, const TreeNode* b) const
    {
        return a->val > b->val;
    }
};
map<char, string> mp;//dfs求字母对应的编码
void dfs(TreeNode* p, string now)
{
    if (p->letter>='A' && p->letter<='F') mp[p->letter] = now;
    if (p->left) dfs(p->left, now + "0");
    if (p->right) dfs(p->right, now + "1");
}

int main()
{
    string ss = "BADCADFEED";
    int a[6] = {27, 8, 15, 15, 30, 5};
    priority_queue<TreeNode*, vector<TreeNode*>, cmp> heap;
    for (int i = 0; i < 6; i++)
        heap.push(new TreeNode(i+'A', a[i]));
    TreeNode* p;
    while (!heap.empty()){//合并值最小的两个,建立二叉树
        p = heap.top();
        heap.pop();
        if (heap.empty()) break;
        TreeNode* q = heap.top();
        heap.pop();
        TreeNode* tmp = new TreeNode('#', p->val+q->val);
        tmp->left = p;
        tmp->right = q;
        heap.push(tmp);
    }
    mp.clear();
    string now = "";
    dfs(p, now);
    //for (auto it : mp) cout << it.first << it.second << endl;
    string new_ss = "";
    for (char c : ss) new_ss += mp[c];
    cout << new_ss << endl;//编码出来的字符串
    for (int i = 0; i < new_ss.size(); i++){
        TreeNode* tmp = p;
        while (tmp->letter == '#'){
            if (new_ss[i]=='0') tmp = tmp->left;
            else tmp = tmp->right;
            i++;
        }
        i--;
        cout << tmp->letter;
    }//由编码求原字符串
    return 0;
}

我把图论里这三个算法都写在一起了,其中Prim算法和Dijkstra算法十分相似,复制以后稍微改改就是,毕竟原理都是取离v0最近的点,而书中这个Kruskal算法我觉得有点并查集的意思,通过找父亲来判断是否有环,反正学就完事了!至于Floyed算法我觉得没啥写的必要了。

图论

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N = 15;

int n, m;
int dis[N];
struct node
{
    int v, w;
    node(int v, int w) : v(v), w(w){}
};

vector<node> mp[N];
struct cmp
{
    bool operator()(const int &a,const int &b)
    {
        return dis[a] > dis[b];
    }
};

struct Node
{
    int u, v, w;
    bool operator<(const Node& a) const
    {
        return w < a.w;
    }
}edge[2*N];

void Prim()//get the node closest to v0, update vk's path
{
    int k, adjvex[n];
    memset(adjvex, 0, sizeof adjvex);
    memset(dis, 0x3f, sizeof dis);
    dis[0] = 0;
    priority_queue<int, vector<int>, cmp> heap;
    for (size_t i = 0; i < mp[0].size(); i++){
        dis[mp[0][i].v] = mp[0][i].w;
        heap.push(mp[0][i].v);
    }
    while (!heap.empty()){
        k = heap.top();
        heap.pop();
        if (dis[k]==0) continue;
        cout << adjvex[k] << " " << k << endl;
        dis[k] = 0;
        for (size_t i = 0; i < mp[k].size(); i++)
        if (dis[mp[k][i].v]>0 && mp[k][i].w < dis[mp[k][i].v]){
            dis[mp[k][i].v] = mp[k][i].w;
            heap.push(mp[k][i].v);
            adjvex[mp[k][i].v] = k;
        }
    }
}

int Find(int *parent, int f)
{
    while (parent[f])
        f = parent[f];
    return f;
}
void Kruskal()//use the shortest path and judge whether there is a cycle
{
    int parent[n];
    memset(parent, 0, sizeof parent);
    for (int i = 0; i < m; i++){
        int u = Find(parent, edge[i].u);
        int v = Find(parent, edge[i].v);
        if (u != v){
            parent[u] = v;
            cout << edge[i].u << " " << edge[i].v << endl;
        }
    }

}
void Dijkstra()
{
    int k, adjvex[n];
    int vis[n];
    memset(vis, 0, sizeof vis);
    memset(adjvex, 0, sizeof adjvex);
    memset(dis, 0x3f, sizeof dis);
    dis[0] = 0;
    //for (size_t i = 0; i < mp[0].size(); i++)
      //  dis[mp[0][i].v] = mp[0][i].w;
    priority_queue<int, vector<int>, cmp> heap;
    heap.push(0);
    while (!heap.empty()){
        k = heap.top();
        heap.pop();
        if (vis[k]) continue;
        vis[k] = 1;
        for (size_t i = 0; i < mp[k].size(); i++)
        if (!vis[mp[k][i].v] && dis[k]+mp[k][i].w < dis[mp[k][i].v]){//这里和prim不同
            dis[mp[k][i].v] = mp[k][i].w + dis[k];
            heap.push(mp[k][i].v);
            adjvex[mp[k][i].v] = k;
        }
    }
    cout << endl;
    for (int i = 1; i < n; i++){
        int now = i;
        while (now){
            cout << now << "->";
            now = adjvex[now];
        }
        cout << endl;
    }
}

int main()
{
    int u, v, w;
    cin >> n >> m;
    for (int i = 0; i < m; i++){
        cin >> u >> v >> w;//Undirected graph
        mp[u].push_back(node(v, w));
        mp[v].push_back(node(u, w));
        edge[i].u = u;
        edge[i].v = v;
        edge[i].w = w;
    }
    cout << endl;
    Prim();
    cout << endl;
    sort(edge, edge+m);
    Kruskal();
    cout << endl;
    Dijkstra();
    return 0;
}
/*
9 15
0 1 10
0 5 11
1 2 18
1 6 16
1 8 12
2 3 22
2 8 8
3 4 20
3 6 24
3 7 16
3 8 21
4 5 26
4 7 7
5 6 17
6 7 19



*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值