• Open Data Structure Templates


    数据结构模板 Chen 2016/12/22

    Open Source in Github: https://github.com/Wasdns/DataStructure-Templates

    前言

    本篇博客的模板,全部是我纯手打的,如果有发现错误,请在下方留言指正:)。欢迎大家参考。

    有一些地方还不是很完善,等过一阵子用C++实现和部分重构下。

    C/C++ 常用字符串函数

    #include <string.h>
    

    strcpy

    char * strcpy( char * dest, const char * src );
    

    功能:把 src 所指由NULL结束的字符串复制到 dest 所指的数组中。
    说明:src 和 dest 所指内存区域不可以重叠且 dest 必须有足够的空间来容纳 src 的字符串。返回指向 dest 结尾处字符(NULL)的指针。

    strcmp

    int strcmp ( const char * str1, const char * str2 );
    

    功能:比较字符串 str1 和 str2。
    说明:
    当s1<s2时,返回值<0
    当s1=s2时,返回值=0
    当s1>s2时,返回值>0

    strlen

    size_t strlen ( const char * str );
    

    功能:计算字符串 str 的长度
    说明:返回 str 的长度,不包括结束符NULL。(注意与 sizeof 的区别)

    C++:StringStream

    #include <sstream>
    
    int a;
    
    stringstream ss;
    ss << "32";
    ss >> a;
    ss.clear();
    

    排序

    相关定义

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    /*存储数组定义*/
    
    int num[100005];
    
    void swap1(int i, int j)
    {
        int t = num[i];
        num[i] = num[j];
        num[j] = t;
    }
    
    /*Printnum 输出*/
    
    void Printnum(int n)
    {
        for (int i = 1; i <= n; i++) {
            cout << num[i] << " ";
        }
        
        cout << endl;
    }
    

    冒泡排序

    /*Bubble_Sort 冒泡排序*/
    
    void Bubble_Sort(int n)
    {
        int i, j;
        
        for (i = 1; i <= n; i++)                //遍历n次
        {
            for (j = 1; j <= n-i; j++)          //每次都把最大数往后排,缩小范围
            {
                if (num[j] > num[j+1])
                {
                    swap1(j, j+1);
                }
            }
        }
    }
    
    void Bubble_Sort_Better(int n)
    {
        int i, j;
        
        for (i = 1; i <= n; i++)
        {
            bool flag = true;
            
            for (j = 1; j <= n-i; j++)
            {
                if (num[j] > num[j+1])
                {
                    flag = false;
                    
                    swap1(j, j+1);
                }
            }
            
            if (flag) break;                    //某一次遍历没有发生交换时,结束
        }
    }
    

    选择排序

    /*Selection_Sort 选择排序*/
    
    void Selection_Sort(int n)
    {
        int i, j;
        
        int rcd;
        
        for (i = 1; i <= n; i++)
        {
            rcd = i;
            
            for (j = i+1; j <= n; j++)
            {
                if (num[j] < num[rcd])          //找出i+1=>n范围内的最小元并前移
                {
                    rcd = j;
                }
            }
            
            swap1(i, rcd);
        }
    }
    

    归并排序

    /*Merge_Sort 归并排序*/
    
    int temp[100005];
    
    void Merge_Array(int l1, int r1, int l2, int r2)
    {
        int p1 = l1;
        int p2 = l2;
        
        int i = 1;
        
        memset(temp, 0, sizeof(temp));
        
        for (i = l1; i <= r2; i++)
        {
            if (p1 > r1)
            {
                temp[i] = num[p2++];
                
                continue;
            }
            
            if (p2 > r2)
            {
                temp[i] = num[p1++];
                
                continue;
            }
            
            if (num[p1] < num[p2])
            {
                temp[i] = num[p1++];
                
                continue;
            }
            
            else
            {
                temp[i] = num[p2++];
                
                continue;
            }
        }
        
        for (i = l1; i <= r2; i++)
        {
            num[i] = temp[i];
        }
        
    }
    
    void Merge_Sort(int l, int r)
    {
        if (l < r)
        {
            int mid = (l+r)/2;
            
            Merge_Sort(l, mid);             //l => mid
            Merge_Sort(mid+1, r);           //mid+1 => r
            
            Merge_Array(l, mid, mid+1, r);  //l => mid => mid+1 => r
        }
    }
    

    快速排序

    /*Quick_Sort 快速排序*/
    
    int Quick_Sort_Adjust(int l, int r)
    {
        int key = l;               //选取第一个元素为基准值
        
        int a, b;
        
        a = l+1;
        
        b = r;
        
        while (a < b)
        {
            bool out_bound = false;
            
            while (1)
            {
                if (num[a] > num[key]) break;
                
                a++;
                
                if (a > r)
                {
                    out_bound = true;
                    
                    break;
                }
            }
            
            while (1)
            {
                if (num[b] < num[key]) break;
                
                b--;
                
                if (b < l)
                {
                    out_bound = true;
                    
                    break;
                }
            }
            
            if (out_bound || a >= b) break;         //如果出现越界或a>=b直接结束
            
            swap1(a, b);
            
            a++;
            b--;
        }
        
        swap1(key, a-1);
        
        return a-1;
    }
    
    void Quick_Sort(int l, int r)
    {
        if (l < r)
        {
            int mid = Quick_Sort_Adjust(l, r);
            
            Quick_Sort(l, mid-1);               //l => mid-1
            Quick_Sort(mid+1, r);               //mid+1 => r
        }
    }
    

    并查集

    并查集

    int fa[100005];
    
    void IniFUS(int n)
    {
        int i;
        
        for (i = 1; i <= n; i++)
        {
            fa[i] = i;
        }
    }
    
    int Find(int x)
    {
        int f = x;
        
        while (f != fa[f])
        {
            f = fa[f];
        }
        
        int i = x, j;
        
        while (i != f)
        {
            j = fa[i];
            
            fa[i] = f;
            
            i = j;
        }
        
        return f;
    }
    
    void Union(int x, int y)
    {
        int xfa = Find(x);
        int yfa = Find(y);
        
        if (xfa != yfa) {
            fa[yfa] = xfa;
        }
    }
    

    邻接表

    struct edge
    {
        edge *next;
        int num;
        int len;
    };
    
    edge eg[100000];
    
    struct head
    {
        edge *next;
        int num;
    };
    
    head h[100000];
    
    void IniList(int n)
    {
        int i;
        
        for (i = 1; i <= n; i++)
        {
            h[i].next = NULL;
            h[i].num = i;
        }
    }
    
    void CreatList(int x, int y, int leng)
    {
        edge *p1, *p2;
        
        p1 = new edge;
        p1 -> next = NULL;
        p1 -> num = y;
        p1 -> len = leng;
        
        p2 = h[x].next;
        
        if (p2 == NULL) {
            h[x].next = p1;
        }
        
        else
        {
            while (p2 -> next != NULL) {
                p2 = p2 -> next;
            }
            
            p2 -> next = p1;
        }
    }
    

    Dijkstra 单点到多点距离(邻接表实现):

    /*
        Dijkstra:
            1.DijInitial
            2.x_HasPath_y
            3.Dijkstra
     */
    
    int pre[100005];                         //最短路节点的前继节点(查询最短路)
    
    int dist[100005];                        //源点到每个节点的最短路距离
    
    bool ins[100005];                        //节点i是否位于已查询节点集合S
    
    void DijInitail(int start, int n)
    {
        int i;
        
        for (i = 1; i <= n; i++)
        {
            dist[i] = maxn;
            
            pre[i] = i;
            
            ins[i] = false;
        }
        
        dist[start] = 0;
        
        edge *p;
        
        p = h[start].next;
        
        while (p != NULL)
        {
            dist[p->num] = p->len;
            
            p = p -> next;
        }
    }
    
    int x_HasPath_y(int x, int y)
    {
        edge *p;
        
        p = h[x].next;
        
        while (p != NULL)
        {
            if (p -> num == y)
            {
                return p -> len;
            }
            
            p = p -> next;
        }
        
        return -1;
    }
    
    int Dijkstra(int start, int find, int n)
    {
        int i, j;
        
        DijInitail(start, n);
        
        ins[start] = true;
        
        for (i = 1; i < n; i++)                     //n-1次
        {
            int addnum = start;                     //记录此时V中最靠近源点的节点
            
            int minlen = 1000000;                   //以及源点到该节点的长度
            
            for (j = 1; j <= n; j++)                //源点从V中挑一个最近节点
            {
                if (ins[j]) continue;               //这个节点在S中,跳过
                
                if (dist[j] < minlen)               //当前到源点距离最小的节点
                {
                    addnum = j;
                    
                    minlen = dist[j];               //更新离源点最近节点的信息
                }
            }
            
            ins[addnum] = true;
            
            for (j = 1; j <= n; j++)                //新来的节点向外得到路径信息
            {                                       //并维护dist
                if (ins[j]) continue;
                
                /* 从源点到当前节点next的距离 + 当前节点next到某个相邻节点j的距离。*/
                /* 如果小于目前源点到节点j的最短距离dist[j],更新dist[j]。       */
                
                int pathlen = x_HasPath_y(addnum, j);
                
                if (pathlen == -1) continue;
                
                int t = dist[addnum] + pathlen;
                
                if (t < dist[j])
                {
                    dist[j] = t;
                    
                    pre[j] = addnum;
                }
            }
            
        }
        
        return dist[find];
    }
    

    Dijkstra 多点到多点(邻接矩阵实现):

    int DijGraph[105][105];               //节点i和j之间的距离:DijGraph[i][j]
    
    int pre[105];                         //最短路节点的前继节点(查询最短路)
    
    int dist[105];                        //源点到每个节点的最短路距离
    
    bool ins[105];                        //节点i是否位于已查询节点集合S
    
    /*
     初始化函数
     */
    
    void Initial(int n)
    {
        for (int i = 1; i <= n; i++)
        {
            ins[i] = false;
            
            pre[i] = -1;
            
            for (int j = 1; j <= n; j++)
            {
                if (i == j) DijGraph[i][j] = 0;
                
                else DijGraph[i][j] = 1000000;
            }
        }
    }
    
    void Dijkstra(int n, int b, int e)
    {
        int i, j;
        
        for (i = 1; i <= n; i++) {                  
            dist[i] = DijGraph[b][i];
        }
        
        dist[b] = 0;
        ins[b] = true;                              
        
        for (i = 2; i <= n; i++)                    
        {
            int next = b;                           
            int minlen = 1000000;                   
            
            for (j = 1; j <= n; j++)                
            {
                if (ins[j]) continue;              
                
                if (dist[j] < minlen) {             
                    
                    next = j;
                    
                    minlen = dist[j];               
                }
            }
            
            ins[next] = true;                       
            
            for (j = 1; j <= n; j++)                
            {                
                if (ins[j]) continue;
                
                int t = dist[next] + DijGraph[next][j];
                
                if (t < dist[j])
                {
                    dist[j] = t;
                    
                    pre[j] = next;
                }
            }
        }
    }
    
    

    Prim

    int Primgh[10000][10000];                        //存储图
    
    bool refer[10005];                               //判断是否在Enew中
    
    /*
        用于初始化的函数
     */
    
    void Initial(int n, int m)
    {
        int i, j;
        
        for (i = 1; i <= n; i++)
        {
            refer[i] = false;
            
            for (j = 1; j <= n; j++)
            {
                if (i == j) {
                    Primgh[i][j] = 0;
                }
                
                else Primgh[i][j] = maxn;
            }
        }
        
        int u, v, w;
        
        for (i = 1; i <= m; i++)
        {
            cin >> u >> v >> w;
            
            Primgh[u][v] = w;
            Primgh[v][u] = w;
        }
    }
    
    /*
        Prim算法,主体部分
     */
    
    int Prim_Alg(int n, int m)
    {
        Initial(n, m);
        
        int i, j, k;
        
        int ans = 0;                
        //最小生成树的路径长度                 
        
        refer[1] = true;            
        //选择点1出发        
        
        //最小生成树一共有n-1条边,因此需要寻找最短边n-1次,基于贪心
        for (i = 1; i <= n-1; i++)  
        {
            int minlen = maxn;      
            //minlen: 在Vnew中的节点所连接的边中,寻找cost最小的边
            
            int rcd = 1;            
            //cost最小的边有两个节点,rcd记录其中的不属于Vnew的节点
            
            for (j = 1; j <= n; j++)        
            {
                if (!refer[j]) continue;    
                //遍历Vnew中的所有节点
                
                int len1 = maxn;            
                //对于Vnew中的某个节点来说,所连接的最短的路径cost大小
                
                int rcd1 = 1;               
                //对于Vnew中的某个节点来说,rcd记录的节点
                
                //贪心,寻找这个节点连接的cost最小的路径
                for (k = 1; k <= n; k++)    
                {
                    if (!refer[k])
                    {
                        if (Primgh[j][k] < len1) {
                            
                            len1 = Primgh[j][k];
                            
                            rcd1 = k;
                        }
                    }
                }
                
                if (len1 < minlen) {        
                    //判断贪心得到的路径是否是全局cost最短
                    
                    minlen = len1;
                    
                    rcd = rcd1;
                }
            }
            
            /*Debug:*/
            //char check = 'A'+rcd-1;
            //cout << "rcd: " << check << endl;
            //cout << "minlen: " << minlen << endl;
            
            refer[rcd] = true;              
            //贪心求出cost最小的路径,rcd记录的节点入Vnew
            rcd = 1;                        
            //重置rcd
            
            ans += minlen;                  
        }
        
        return ans;
    }
    
    

    Kruskal

    struct stedge
    {
        int u, v, len;
    };
    
    bool cmp(stedge s1, stedge s2)
    {
        return s1.len < s2.len;
    }
    
    stedge seg[100000];
    
    int fa[100005];
    
    void Inifa(int n)
    {
        for (int i = 1; i <= n; i++)
        {
            fa[i] = i;
        }
    }
    
    int findfa(int x)
    {
        int f = x;
        
        while (f != fa[f])
        {
            f = fa[f];
        }
        
        int i = x, j;
        
        while (i != f)
        {
            j = fa[i];
            
            fa[i] = f;
            
            i = j;
        }
        
        return f;
    }
    
    int main()
    {
        int i, n, m;
        
        cin >> n >> m;
        
        Inifa(n);
        
        int u, v, w;
        
        for (i = 1; i <= m; i++)
        {
            cin >> u >> v >> w;
            
            seg[i].u = u;
            seg[i].v = v;
            seg[i].len = w;
        }
        
        sort(seg+1, seg+m+1, cmp);
        
        int cnt = 0, lencnt = 0;
        
        for (i = 1; i <= m; i++)
        {
            int fa1 = findfa(seg[i].u);
            int fa2 = findfa(seg[i].v);
            
            if (fa1 == fa2) continue;
            
            cnt++;
            
            lencnt += seg[i].len;
            
            fa[fa1] = fa2;         //一定是祖先找祖先合并
            
            if (cnt == n-1) break;
        }
        
        cout << lencnt;
        
        return 0;
    }
    

    树的序遍历

    //
    //  main.cpp
    //  Tree2
    //
    //  Created by wasdns on 16/12/19.
    //  Copyright © 2016年 wasdns. All rights reserved.
    //
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    struct Node
    {
        int num;
        
        Node *l, *r;
    };
    
    int preorder[100005];
    
    int midorder[100005];
    
    int aftorder[100005];
    
    Node *node[100005];
    
    int n;
    
    int tot = 1;    //记录aftorder
    
    
    /*
        Ininode函数:用于初始化节点
     */
    void Ininode()
    {
        int i;
        
        for (i = 1; i <= n; i++)
        {
            Node *p = new Node;
            
            p -> num = i;
            p -> l = NULL;
            p -> r = NULL;
            
            node[i] = p;
        }
    }
    
    /*
        FindRoot函数:根据后序、中序建树
     */
    Node* FindRoot(int aft_l, int aft_r, int mid_l, int mid_r)
    {
        if (aft_r - aft_l < 0) return NULL;
        
        Node *root = new Node;
        
        root -> num = aftorder[aft_r];
        
        if (aft_l == aft_r)
        {
            root -> l = NULL;
            root -> r = NULL;
            
            return root;
        }
        
        int index;
        
        for (index = mid_l; index <= mid_r; index++)
        {
            if (midorder[index] == aftorder[aft_r]) break;
        }
        
        root -> r = FindRoot(aft_r-(mid_r-index), aft_r-1, index+1, mid_r);
        root -> l = FindRoot(aft_l, aft_r-(mid_r-index)-1, mid_l, index-1);
        
        return root;
    }
    
    
    /*
        FindRoot函数:根据先序和中序建树。
     */
    Node* FindRoot1(int pre_l, int pre_r, int mid_l, int mid_r)
    {
        if (pre_r - pre_l < 0) return NULL;
        
        Node* root = new Node;
        
        /*将先序列表中最左边的节点作为root*/
        root -> num = preorder[pre_l];
        
        if (pre_l == pre_r)
        {
            root -> l = NULL;
            root -> r = NULL;
            
            return root;
        }
        
        /*在中序中找到root所在的位置,用index表示*/
        int index;
        
        for (index = mid_l; index <= mid_r; index++)
        {
            if (midorder[index] == preorder[pre_l]) break;
        }
        
        /*说明:利用index进行递归,分成左子树和右子树。        */
        /*同时将先序序列和后序序列进行划分,将位置作为递归的参数。*/
        root -> l = FindRoot1(pre_l+1, pre_l+(index-mid_l), mid_l, index-1);
        root -> r = FindRoot1(pre_l+(index-mid_l)+1, pre_r, index+1, mid_r);
        
        return root;
    }
    
    /*
        CalAftorder函数:根据给定的树来计算后序序列
     */
    void CalAftorder(Node *head)
    {
        if (head == NULL) return ;
        
        CalAftorder(head -> l);
        CalAftorder(head -> r);
        
        aftorder[tot++] = head -> num;
    }
    
    
    /*
        CalPreorder函数:根据给定的树来计算先序序列
     */
    void CalPreorder(Node *head)
    {
        if (head == NULL) return ;
        
        preorder[tot++] = head -> num;
        
        CalPreorder(head -> l);
        CalPreorder(head -> r);
    }
    
    
    /*
        Print函数:输出先序、后序序列
     */
    void Print()
    {
        int i;
        
        for (i = 1; i <= n; i++) {
            cout << preorder[i] << " ";
        }
        
        cout << endl;
        
        for (i = 1; i <= n; i++) {
            cout << aftorder[i] << " ";
        }
        
        cout << endl;
    }
    

    优先队列 STL

    值大 => 优先级高

    #include <iostream>
    #include <queue>
    using namespace std;
    
    priority_queue<int> q;
    

    值小 => 优先级高

    #include <iostream>
    #include <functional>
    #include <queue>
    using namespace std;
    
    struct cmp
    {
        bool operator() (int x,int y) {
            return x > y;
        }
    };
    
    priority_queue<int, vector<int>, cmp> q;
    

    结构体:

    struct node
    {
          int x, y;
           friend bool operator < (node a, node b)
          {
                 return a.x > b.x; //结构体中,x小的优先级高
          }
    };
    priority_queue<node>q;//定义方法
    //在该结构中,y为值, x为优先级。
    //通过自定义operator<操作符来比较元素中的优先级。
    //在重载”<”时,最好不要重载”>”,可能会发生编译错误
    

    手写Heap堆:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    int size = 0;
    
    int Heap[100005];
    
    /*
         维护函数keep
     */
    void keep(int son)
    {
        int fa = son/2;
        
        while (fa >= 1 && Heap[fa] > Heap[son])
        {
            int t = Heap[fa];
            Heap[fa] = Heap[son];
            Heap[son] = t;
            
            son = fa;
            fa = fa/2;
        }
    }
    
    /*
        初始化函数IniHeap
     */
    void IniHeap()
    {
        int i;
        
        for (i = size; i >= 1; i--)
        {
            keep(i);
        }
    }
    
    /*
        InsProtect函数:插入新节点并维护
     */
    void InsProtect(int a)
    {
        Heap[++size] = a;
        
        keep(size);
    }
    
    /*
        DelMin函数:删除最小元并维护
     */
    int DelMin()
    {
        int minum = Heap[1];
        
        int t = Heap[size];
        
        Heap[1] = t;
        
        size--;
        
        IniHeap();
        
        return minum;
    }
    

    Hash函数

    Index哈希函数例1:

    #include<iostream> 
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    using namespace std; 
    const int maxn =1000005; 
    int num[maxn]; 
    char a[maxn],str[10]; 
       
    int IndexHash(char *key) 
    { 
        int hashval = 0; 
        while (*key != '')    hashval = (hashval<<5) + *key++; 
        return hashval; 
    } 
       
       
    int main() 
    { 
        //freopen("data.txt","r",stdin); 
        //freopen("2.txt","w",stdout);  
        int n,m,k,i,p = 0; 
        memset(str,0,sizeof(str)); 
        scanf("%d%d%d",&n,&m,&k); 
        scanf("%s",a); 
        for (i = 0;i <= n - k;i++) 
        { 
            strncpy(str,a + i,k); 
            int hashval = IndexHash(str); 
            num[p++] = hashval; 
        } 
        sort(num,num+p); 
        int res = 1; 
        for (i = 1;i < p;i++) 
        { 
            if (num[i] != num[i-1]) res++; 
        } 
        printf("%d
    ",res); 
        return 0; 
    }
    

    例2:

    //
    //  main.cpp
    //  searchme
    //
    //  Created by wasdns on 16/12/12.
    //  Copyright © 2016年 wasdns. All rights reserved.
    //
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define mod 999983                          //int范围内取最大的素数
    #define maxn 1000005
    using namespace std;
    
    /*
        Hash函数:IndexHash
     */
    
    int IndexHash(char *s)
    {
        int hashval = 0;
        
        while (*s != '') {
            hashval = (hashval << 5) + *s++;
        }
        
        return hashval % mod;
    }
    
    char searchname[maxn][10];                  //你的名字
    
    int head[maxn];                             //邻接表的头数组
    
    int lnext[maxn];                            //邻接表的节点数组
    
    int tot = 1;                                //第tot个字符串
    
    /*
        AddNode创建邻接表函数:
            在head[hashval]中存指向单链表的指针
            插入时,现有head的值存入lnext[tot]
            之后使head[hashval]成为新的节点
            相当于不断在链表的首部进行插入
     */
    
    void AddNode(int hashval)
    {
        lnext[tot] = head[hashval];
        
        head[hashval] = tot;
        
        tot++;
    }
    
    /*
        询问函数:
            通过IndexHash得到hash值
            利用head[hashval]找到指向对应hash值的单链表
            遍历单链表,找到 -> 计数器++。
     */
    
    void query(int q)
    {
        int cnt = 0;
        
        for (int i = 1; i <= q; i++)
        {
            int hashval = 0;
            
            char findname[10];
            
            scanf("%s", findname);
            
            hashval = IndexHash(findname);
            
            for (int j = head[hashval]; j != -1; j = lnext[j])
            {
                if (strcmp(searchname[j], findname) == 0) {
                    cnt++;
                }
            }
        }
        
        printf("%d
    ", cnt);
    }
    
    int main()
    {
        memset(head, -1, sizeof(head));
        memset(lnext, -1, sizeof(lnext));
        
        int n, m;
        
        cin >> n >> m;
        
        int i;
        
        for (i = 1; i <= n; i++)
        {
            scanf("%s", searchname[i]);
            
            int hashval = IndexHash(searchname[i]);
            
            AddNode(hashval);
        }
        
        cout << endl;
        
        query(m);
        
        return 0;
    }
    

    2016/12/29

  • 相关阅读:
    数学笔记目录
    机器学习笔记目录
    物理学笔记目录
    二阶递推公式的通项公式
    分析Analysis 笔记
    从傅里叶变换到小波变换
    电动力学 期末复习
    电动力学 期中复习
    热学 期中复习
    理论力学第一章 Lagrange方程
  • 原文地址:https://www.cnblogs.com/qq952693358/p/6232516.html
Copyright © 2020-2023  润新知