zoukankan      html  css  js  c++  java
  • HXD的DS

    1.线性表的增删改查

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node
    {
    	int element;//数据域
    	struct node * link;//指针域
    }Node;
    
    typedef struct headerList
    {
    	Node * head;
    	int n;
    }HeaderList;
    
    int Init(HeaderList * h);//单链表初始化
    int Find(HeaderList h, int i, int *x);//单链表的查找
    int Insert(HeaderList * h, int i, int x);//单链表的插入
    int Delete(HeaderList * h, int i);//单链表的删除
    int Output(HeaderList * h);//单链表的输出
    void Change(HeaderList * h, int i, int x);//修改元素
    void Destroy(HeaderList * h);//单链表的撤销
    
    HeaderList list;
    
    int main()
    {
    	Init(&list);//初始化
    	for (int i = 0; i < 9; i++) Insert(&list, i - 1, i);
    
    	printf("THE LIST IS:
    ");
    	Output(&list);
    
    	Delete(&list, 0);
    	printf("
    AFTER DELETE THE LIST IS:
    ");
    	Output(&list);
    
    	Change(&list, 3, 22);
    	printf("
    AFTER CHANGE
    ");
    	Output(&list);
    
    	int temp;
    	Find(list, 0, &temp);
    	printf("
    FIND VALUE: %d
    ", temp);
    
    	Destroy(&list);
    
    	system("pause");
    	return 0;
    }
    
    int Init(HeaderList * h)
    {
    	h->head = (Node *)malloc(sizeof(Node));
    
    	if (!h->head) return 0;
    
    	h->head->link = NULL;
    	h->n = 0;
    
    	return 1;
    }
    
    int Find(HeaderList h, int i, int *x)
    {
    	Node *p;
    
    	if (i < 0 || i > h.n - 1) return 0;//判断下标越界
    
    	p = h.head;//c从头节点查找
    	for (int j = 0; j <= i; j++) p = p->link;
    
    	*x = p->element;
    	return 1;
    }
    
    int Insert(HeaderList * h, int i, int x)
    {
    	Node *p, *q;
    
    	if (i < -1 || i > h->n - 1) return 0;//判断越界
    
    	p = h->head;
    	for (int j = 0; j <= i; j++) p = p->link;
    
    	q = (Node *)malloc(sizeof(Node));
    	q->element = x;
    	q->link = p->link;
    	p->link = q;
    	h->n++;
    
    	return 1;
    }
    
    int Delete(HeaderList * h, int i)
    {
    	Node *p, *q;
    
    	if (!h->n) return 0;//判断是否为空
    	if (i < 0 || i > h->n - 1) return 0;//判断越界
    
    	q = h->head;
    	for (int j = 0; j < i; j++) q = q->link;
    	p = q->link;
    	q->link = p->link;
    	free(p);
    	h->n--;
    
    	return 1;
    }
    
    int Output(HeaderList * h)
    {
    	Node *p;
    
    	if (!h->n) return 0;//判断是否为空
    
    	p = h->head->link;
    
    	while (p)
    	{
    		printf("%d ", p->element);
    		p = p->link;
    	}
    
    	return 1;
    }
    
    void Destroy(HeaderList * h)
    {
    	Node *p;
    	while (h->head)
    	{
    		p = h->head->link;
    		free(h->head);
    		h->head = p;
    	}
    }
    
    void Change(HeaderList * h, int i, int x)
    {
    	Node *p;
    
    	if (i < 0 || i > h->n - 1) return;//判断下标越界
    
    	p = h->head;//c从头节点查找
    	for (int j = 0; j <= i; j++) p = p->link;
    
    	p->element = x;
    }
    

    2.两个有序单向链表的归并(数组模拟的静态链表实现)

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int N = 10010;
    
    int h[3], e[N], ne[N], idx;//h数组为头指针,h[0], h[1]为两个有序链表,归并后的链表是h[2]
    
    void add(int a, int b)
    {
        e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    }
    
    int main()
    {
        memset(h, -1, sizeof h);//初始化头指针
        
        //构造两条降序链表
        for (int i = 0; i < 10; i ++ )
        {
            add(0, i);
            add(1, i * i);
        }
        
        puts("");
        
        int i = h[0], j = h[1];
        for ( ; ~i && ~j; )
        {
            int a = e[i], b = e[j];
            
            if (e[i] >= e[j])
            {
                add(2, e[i]);
                i = ne[i];//指向下一个结点
            }
            else
            {
                add(2, e[j]);
                j = ne[j];//指向下一个结点
            }
        }
        
        //扫尾
        while (~i) add(2, e[i]), i = ne[i];
        while (~j) add(2, e[j]), j = ne[j];
        
        for (int i = h[2]; ~i; i = ne[i])
            cout << e[i] << ' ';
        
        puts("");
        
        return 0;
    }
    

    3.栈与队列

    #include <iostream>
    
    using namespace std;
    
    const int N = 1010;
    
    int q[N];
    int cnt = 20;//假设有20张票
    
    int main()
    {
        int hh = 0, tt = -1;
        int i = 1;//队列中人的序号
        
        for (int j = 1; j <= 3; j ++ )
            q[ ++ tt] = i ++ ;//假设初始队伍中有3个人
        
        cnt -= 3;
        
        while (hh <= tt)
        {
            auto t = q[hh ++ ];//队头买完票出队
            
            cnt -- ;//票余量减一
            if (cnt >= 0)//如果还有余票
                q[ ++ tt] = i ++ ;
                
            cout << t << ' ';//输出队伍
        }
        
        return 0;
    }
    

    4.二叉树的遍历(先,中,后,BFS层次遍历)

    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <queue>
    
    using namespace std;
    
    typedef struct btnode
    {
    	char element;
    	struct btnode * lc, *rc;
    }BTNode;
    
    BTNode * PreCreateBT(BTNode * t);//先序遍历构建二叉树
    void PreOrderTraversal(BTNode * t);//先序遍历二叉树,DFS递归做法
    void InOrderTraversal(BTNode * t);//中序遍历二叉树
    void PostOrderTraversal(BTNode * t);//后序遍历二叉树
    void BFS(BTNode * t);//层次遍历二叉树,BFS宽搜
    
    int main()
    {
    	BTNode * root = NULL;
    	root = PreCreateBT(root);
    
    	//先序遍历二叉树
    	cout << "PreOrderTraversal BT tree is :" << endl;
    	PreOrderTraversal(root);
    	puts("");
    
    	//中序遍历二叉树
    	cout << "InOrderTraversal BT tree is :" << endl;
    	InOrderTraversal(root);
    	puts("");
    
    	//后序遍历二叉树
    	cout << "PostOrderTraversal BT tree is :" << endl;
    	PostOrderTraversal(root);
    	puts("");
    
    	//宽度优先遍历二叉树
    	cout << "宽度遍历二叉树:" << endl;
    	BFS(root);
    	puts("");
    
    	system("pause");
    	return 0;
    }
    
    BTNode * PreCreateBT(BTNode * t)
    {
    	char ch;
    	ch = getchar();
    
    	if (ch == '#')
    		t = NULL;//空结点
    	else
    	{
    		t = (BTNode *)malloc(sizeof(BTNode));
    		t->element = ch;
    		t->lc = PreCreateBT(t->lc);//构造左儿子
    		t->rc = PreCreateBT(t->rc);//构造右儿子
    	}
    
    	return t;
    }
    
    void PreOrderTraversal(BTNode * t)
    {
    	if (!t)//树空返回
    		return;
    
    	cout << t->element;
    	PreOrderTraversal(t->lc);//递归左儿子
    	PreOrderTraversal(t->rc);//递归右儿子
    }
    
    void InOrderTraversal(BTNode * t)
    {
    	if (!t)//树空返回
    		return;
    
    	InOrderTraversal(t->lc);//递归左儿子
    	cout << t->element;
    	InOrderTraversal(t->rc);//递归右儿子
    }
    
    void PostOrderTraversal(BTNode * t)
    {
    	if (!t)//树空返回
    		return;
    
    	PostOrderTraversal(t->lc);//递归左儿子
    	PostOrderTraversal(t->rc);//递归右儿子
    	cout << t->element;
    }
    
    void BFS(BTNode * t)
    {
    	queue<BTNode *> q;
    	q.push(t);//根结点入队
    
    	while (q.size())
    	{
    		auto t = q.front();//取队头
    		q.pop();//队头出队
    
    		cout << t->element;
    
    		if (t->lc) q.push(t->lc);//如果存在左儿子,入队
    		if (t->rc) q.push(t->rc);//如果存在右儿子,入队
    	}
    }
    
    

    5.哈夫曼树的搭建,编码与解码的实现

    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <string>
    
    using namespace std;
    
    const int N = 30;
    
    struct leaf
    {
    	int value;
    	int parent, lc, rc;//存放父节点,左儿子,右儿子的下标
    };
    
    map<int, char> m1;//权重与字符的映射
    map<int, int> m2;//权重与对应结构体下标的映射
    map<int, int> m3;//权重与对应结构体下标的反映射
    int h[N], idx;//数组模拟的小根堆
    int cnt;//字符的数量
    leaf *root = new leaf[N << 1];//申请哈夫曼树所需的空间,结构体数组
    string s;//存放字符的哈夫曼编码
    
    void down(int u);//小根堆的down操作
    void up(int u);//小根堆的up操作
    void PrintTree(int t);//打印字符和对应的哈夫曼编码
    void CrackCode(string str);//解码
    
    int main()
    {
    	char ch;//字符
    	int rank;//权重
    
    	for (int i = 0; i < 2 * N; i++)
    		root[i].parent = root[i].lc = root[i].rc = -1;
    
    	while (cin >> ch >> rank && ch != '#')
    	{
    		root[cnt].value = rank;//初始化只有根结点的森林
    		m1[rank] = ch;//构造权重与字符的映射
    		m3[cnt] = rank;//构造权重与结构体下标的映射
    		m2[rank] = cnt++;//构造权重与结构体下标的反映射
    		h[++idx] = rank;//权重入堆
    	}
    	for (int i = idx / 2; i; i--) down(i);//O(n)的建堆方式,从倒数第二层开始down下去
    
    	int n = cnt;
    	for (int i = n; i < 2 * n - 1; i++)
    	{
    		int lchild, rchild;
    
    		if (idx >= 2)
    		{
    			lchild = m2[h[1]];//取出权重最小的权重下标作为左儿子
    			h[1] = h[idx--], down(1);//出堆并维持小根堆
    			rchild = m2[h[1]];
    
    			h[1] = h[idx--], down(1);//出堆并维持小根堆
    
    									 //找父结点
    			root[lchild].parent = i;
    			root[rchild].parent = i;
    
    			//找左右儿子
    			root[i].lc = lchild;
    			root[i].rc = rchild;
    
    			//父结点权重为左右儿子权重和
    			root[i].value = root[lchild].value + root[rchild].value;
    
    			//构造父结点和对应结构体数组下标的映射
    			m3[cnt] = root[i].value;
    			m2[root[i].value] = cnt++;
    
    			h[++idx] = root[i].value;//新的结点入堆
    			up(idx);//维持小根堆
    
    		}
    	}
    
    	cout << endl << "字符编码:" << endl;
    	PrintTree(m2[h[1]]);
    
    	string str;
    	cout << endl << "Input a string :(二进制字符串)" << endl;
    	cin >> str;
    
    	CrackCode(str);//解码
    
    	delete[] root;
    
    	system("pause");
    	return 0;
    }
    
    void down(int u)
    {
    	int t = u;
    	if (u * 2 <= idx && h[u * 2] < h[t]) t = u * 2;
    	if (u * 2 + 1 <= idx && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    
    	if (u != t)
    	{
    		swap(h[t], h[u]);
    		down(t);
    	}
    }
    
    void up(int u)
    {
    	while (u / 2 && h[u] < h[u / 2])
    	{
    		swap(h[u / 2], h[u]);
    		u /= 2;
    	}
    }
    
    void PrintTree(int t)
    {
    	if (root[t].lc < 0)//打印叶子结点
    	{
    		cout << m1[root[t].value] << ' ';
    		cout << s << endl;
    		return;
    	}
    	string temp;
    	temp = s;
    
    	s += '0';
    	PrintTree(root[t].lc);
    	s = temp;//恢复到递归前的状态
    	s += '1';
    	PrintTree(root[t].rc);
    	s = temp;//恢复到递归前的状态
    }
    
    void CrackCode(string str)
    {
    	int ini = m2[h[1]];//从根结点开始找
    	for (int i = 0; str[i]; i++)
    	{
    		int t = str[i] - '0';
    
    		if (!t)//t为0,向左儿子移动
    			ini = root[ini].lc;
    		else//否则向右儿子移动
    			ini = root[ini].rc;
    
    		if (root[ini].lc < 0)//到达叶结点
    		{
    			cout << m1[root[ini].value];
    			ini = m2[h[1]];//重新从根结点搜索
    		}
    	}
    }
    
    

    6.Prim求最小生成树

    n个点m条边,接下来m行的三个数a b c表示存在从a到b权值为c的一条边

    求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。

    输入样例:

    4 5
    1 2 1
    1 3 2
    1 4 3
    2 3 2
    3 4 4
    

    输出样例:

    6
    
    代码:
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    const int N = 510, INF = 0x3f3f3f3f;
    
    int g[N][N], dist[N];
    bool st[N];
    int n, m;
    
    int prim()
    {
        memset(dist, 0x3f, sizeof dist);
        
        int res = 0;
        
        for (int i = 0; i < n; i ++ )
        {
            int t = -1;
            for (int j = 1; j <= n; j ++ )
                if(!st[j] && (t == -1 || dist[t] > dist[j]))
                    t = j;
            
            if(i && dist[t] == INF) return INF;
            if(i) res += dist[t];
            
            st[t] = true;
            
            for (int j = 1; j <= n; j ++ )
                dist[j] = min(dist[j], g[t][j]);
        }
        
        return res;
    }
    
    int main()
    {
        memset(g, 0x3f, sizeof g);
        
        scanf("%d%d", &n, &m);
        while (m -- )
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            
            g[a][b] = g[b][a] = min(g[a][b], c);
        }
        
        int t = prim();
        
        if(t == INF) puts("impossible");
        else printf("%d
    ", t);
        
        return 0;
    }
    

    7.最短路算法(适用于稠密图的朴素版Dijkstra与堆优化版适用于稀疏图的Dijkstra算法)

    1.适用于稠密图的朴素版Dijkstra算法(O(n²))

    输入样例:

    3 3
    1 2 2
    2 3 1
    1 3 4
    

    输出样例:

    3
    
    代码:
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    const int N = 510;
    
    int g[N][N], dist[N];
    int n, m;
    bool st[N];
    
    int dijkstra()
    {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        
        for (int i = 0; i < n - 1; i ++ )
        {
            int t = -1;
            for (int j = 1; j <= n; j ++ )
                if(!st[j] && (t == -1 || dist[t] > dist[j]))
                    t = j;
                
            for (int j = 1; j <= n; j ++ )
                dist[j] = min(dist[j], dist[t] + g[t][j]);
            
            st[t] = true;
        }
        
        if(dist[n] == 0x3f3f3f3f) return -1;
        else return dist[n];
    }
    
    int main()
    {
        memset(g, 0x3f, sizeof g);
        
        cin >> n >> m;
        
        while ( m -- )
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            
            g[a][b] = min(g[a][b], c);
        }
        
        printf("%d
    ", dijkstra());
        
        return 0;
    }
    
    2.堆优化版适用于稀疏图的Dijkstra(O(mlogn))(m边数 ,n点数)

    输入样例:

    3 3
    1 2 2
    2 3 1
    1 3 4
    

    输出样例:

    3
    
    代码:
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    typedef pair<int, int> PII;
    
    const int N = 1e6 + 10;
    
    int n, m;
    int h[N], w[N], e[N], ne[N], idx;
    int dist[N];
    bool st[N];
    
    void add(int a, int b, int c)
    {
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
    }
    
    int dijkstra()
    {
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        priority_queue<PII, vector<PII>, greater<PII>> heap;
        heap.push({0, 1});
    
        while (heap.size())
        {
            auto t = heap.top();
            heap.pop();
    
            int ver = t.second, distance = t.first;
    
            if (st[ver]) continue;
            st[ver] = true;
    
            for (int i = h[ver]; i != -1; i = ne[i])
            {
                int j = e[i];
                if (dist[j] > dist[ver] + w[i])
                {
                    dist[j] = dist[ver] + w[i];
                    heap.push({dist[j], j});
                }
            }
        }
    
        if (dist[n] == 0x3f3f3f3f) return -1;
        return dist[n];
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
    
        memset(h, -1, sizeof h);
        while (m -- )
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add(a, b, c);
        }
    
        cout << dijkstra() << endl;
    
        return 0;
    }
    
    

    8.归并排序+快速排序+堆排序

    三个排序的输入一致,第一行为n表示数字个数,第二行输入n个数字

    (1).归并排序
    #include <iostream>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    int q[N], temp[N], n;
    
    void merge_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int mid = l + r >> 1;
        
        merge_sort(q, l, mid), merge_sort(q, mid + 1, r);
        
        int k = 0, i = l, j = mid + 1;
        
        while (i <= mid && j <= r)
            if(q[i] <= q[j]) temp[k ++ ] = q[i ++ ];
            else temp[k ++ ] = q[j ++ ];
        
        while (i <= mid) temp[k ++ ] = q[i ++ ];
        while (j <= r) temp[k ++ ] = q[j ++ ];
        
        for (int i = l, j = 0; i <= r; i ++ , j ++ ) q[i] = temp[j];
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d", q + i);
        
        merge_sort(q, 0, n - 1);
        
        for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
        
        return 0;
    }
    
    (2).快速排序
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1e6 + 10;
    
    int q[N], n;
    
    void quick_sort(int q[], int l, int r)
    {
        if(l >= r) return;
        
        int x = q[l + r >> 1], i = l - 1, j = r + 1;
        while(i < j)
        {
            do i ++ ; while(q[i] < x);
            do j -- ; while(q[j] > x);
            
            if(i < j) swap(q[i], q[j]);
        }
        
        quick_sort(q, l, j), quick_sort(q, j + 1, r);
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i ++ ) scanf("%d", q + i);
        
        quick_sort(q, 0, n - 1);
        
        for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);
        
        return 0;
    }
    
    (3).堆排序
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    
    int h[N], idx;
    int n;
    
    
    void down(int u)
    {
        int t = u;
        if(u * 2 <= idx && h[u * 2] < h[t]) t = u * 2;
        if(u * 2 + 1 <= idx && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        
        if(u != t)
        {
            swap(h[t], h[u]);
            down(t);
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i ++ ) scanf("%d", h + i);
        idx = n;
        
        for (int i = n / 2; i; i -- ) down(i);
        
        while (n -- )
        {
            printf("%d ", h[1]);
            h[1] = h[idx -- ];
            down(1);
        }
        puts("");
        
        return 0;
    }
    
  • 相关阅读:
    11. Container With Most Water
    9. Palindrome Number
    375. 猜数字大小 II leetcode java
    leetcode 72 编辑距离 JAVA
    73. 矩阵置零 leetcode JAVA
    快速排序 JAVA实现
    63. 不同路径 II leetcode JAVA
    重写(override)与重载(overload)
    62 不同路径 leetcode JAVA
    leetcode 56 合并区间 JAVA
  • 原文地址:https://www.cnblogs.com/scl0725/p/13939973.html
Copyright © 2011-2022 走看看