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;
}
原文地址:https://www.cnblogs.com/scl0725/p/13939973.html