数据结构代码常用模板

线性表

顺序表

#include <iostream>
#include <stdlib.h>
using namespace std;
#define ll long long
#define InitSize 10000 // 默认最大长度
ll t, ans;

typedef struct
{
    int *data;   // 指示动态分配数组的指针
    int MaxSize; // 顺序表的最大容量
    int length;  // 顺序表的当前长度
} SeqList;

void InitList(SeqList &L) // 初始化顺序表
{
    L.data = (int *)malloc(InitSize * sizeof(int)); // data理解为数组
    L.length = 0;                                   // 记录长度
    L.MaxSize = InitSize;                           // 最大尺寸
}

void IncreaseSize(SeqList &L, int len) // 顺序表扩容
{
    int *p = L.data;
    L.data = (int *)malloc((L.MaxSize + len) * sizeof(int)); // 重新开辟新容量给data
    for (int i = 0; i < L.length; i++)                       // 数据移动
    {
        L.data[i] = p[i];
    }
    L.MaxSize = L.MaxSize + len;
    free(p); // 清理临时数据p
}

int Insert(SeqList *L, int i, int x) // 顺序表输入
{
    int j;
    if (i < -1 || i > L->length - 1)
        return 0;
    if (L->length == L->MaxSize)
        return 0;
    for (j = L->length - 1; j > i; j--)
    {
        L->data[j + 1] = L->data[j];
    }
    L->data[i + 1] = x;
    L->length = L->length + 1;
    return 1;
}

void Inverse(SeqList *L, int length) // 顺序表逆置
{
    int i, temp;
    for (i = 0; i < length / 2; i++)
    {
        temp = L->data[i];
        L->data[i] = L->data[length - 1 - i];
        L->data[length - 1 - i] = temp;
    }
}

int Output(SeqList L) // 顺序表输出
{
    int i;
    if (!L.length)
        return 0;
    for (i = 0; i <= L.length - 1; i++)
        printf("%d ", L.data[i]); // 从前往后逐个输出元素
    return 1;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    ll t, n, x, y, num;
    cin >> t;
    while (t--)
    {
        SeqList L;
        InitList(L);
        cin >> n >> x >> y;
        for (int i = 0; i < n; i++)
        {
            cin >> num;
            Insert(&L, i - 1, num);
        }
        Inverse(&L, n);
        Output(L);
    }

    return 0;
}

单链表

指针L指向头结点

#include <stdlib.h>
#include <iostream>
using namespace std;
int n, k;

typedef struct LNode
{                       // 定义单链表结点类型
    int data;           // 数据域
    struct LNode *next; // 指针域
} LNode, *LinkList;     // LNode *L == LinkList L
// 设p为指向链表结点的结构体指针,则*p表示结点本身,可以用p->data或(*p).data访问*p这个结点的数据域

// 初始化单链表
bool InitList(LinkList &L) // 带&可以将传入的L修改后带回,不带&会对一个L的复制品进行操作
{
    L = (LNode *)malloc(sizeof(LNode));
    L->next = NULL;
    return true;
}

// 头插法建立单链表
LinkList HeadInsert(LinkList &L, int n) // 插入n个元素
{
    int x;
    for (int i = 1; i <= n; i++)
    {
        cin >> x;
        LNode *s = (LNode *)malloc(sizeof(LNode)); // 新插入结点s
        s->data = x;
        s->next = L->next;
        L->next = s;
    }
    return L;
}

// 尾插法建立单链表
LinkList TailInsert(LinkList &L, int n)
{
    LNode *s, *r = L; // r为尾指针
    int x;
    for (int i = 1; i <= n; i++)
    {
        cin >> x;
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;
    }
    r->next = NULL;
    return L;
}

// 单链表遍历
void PrintList(LinkList L)
{
    LNode *p = L->next;
    while (p)
    {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

// 求单链表的长度
int Length(LinkList L)
{
    LNode *p = L->next;
    int len = 0;
    while (p)
    {
        len++;
        p = p->next;
    }
    return len;
}

// 按值查找:查找x在L中的位置,返回一个结点
LinkList LocateElem(LinkList L, int x)
{
    LNode *p = L->next;
    while (p && p->data != x)
    {
        p = p->next;
    }
    return p;
}

// 删除指定值k
void DeleteChange(LinkList &L, int k)
{
    LNode *p = L;
    LNode *s;
    while (p)
    {
        if (p->data == k)
        {
            if (p == L)
            {
                L = p->next; // 更该首地址
            }
            else
                s->next = p->next; // 删除,让上一个节点的next直接链接到下一个节点
        }
        else
            s = p; // s表示上一个节点
        p = p->next;
    }
}

// 按位查找:查找在单链表L中第i个位置的结点
LNode *GetElem(LinkList L, int i)
{
    int j = 1;
    LNode *p = L->next;
    if (i == 0)
        return L;
    if (i < 1)
        return NULL;
    while (p && j < i)
    {
        p = p->next;
        j++;
    }
    return p; // 如果i大于表长,p=NULL,直接返回p即可
}

// 将x插入到单链表L的第i个位置上
void Insert(LinkList &L, int i, int x)
{
    LNode *p = GetElem(L, i - 1);
    LNode *s = (LNode *)malloc(sizeof(LNode));
    s->data = x;
    s->next = p->next;
    p->next = s;
}

// 删除操作:将单链表中的第i个结点删除
void Delete(LinkList &L, int i)
{
    if (i < 1 || i > Length(L))
        cout << "删除失败" << endl;
    return;
    LNode *p = GetElem(L, i - 1);
    LNode *q = p->next;
    p->next = q->next;
    free(q);
}

// 判空操作
bool Empty(LinkList L)
{
    if (L->next == NULL)
    {
        // cout << "空表" << endl;
        return true;
    }
    else
    {
        // cout << "不是空表" << endl;
        return false;
    }
}

int main()
{
    cin >> n;             // n个数据
    LinkList L;           // 定义链表
    InitList(L);          // 初始化链表
    L = TailInsert(L, n); // 尾插法建立单链表
    PrintList(L);         // 输出单链表
    return 0;
}

循环单链表

题目:循环单链表的基本运算
http://qdacm.openjudge.cn/ds202402/07/

#include <iostream>
using namespace std;

typedef struct LNode
{
    char data;
    struct LNode *next;
} LNode, *LinkList;

void init(LinkList &L)
{
    L = (LNode *)malloc(sizeof(LNode));
    L->next = L;
}

void push(LinkList &L)
{
    int n;
    cin >> n;
    if (n == 0)
        return;
    LNode *p;
    p = (LNode *)malloc(sizeof(LNode));
    cin >> p->data;
    p->next = L;
    L->next = p;
    n--;
    while (n--)
    {
        LNode *p1;
        p1 = (LNode *)malloc(sizeof(LNode));
        cin >> p1->data;
        p1->next = L;
        p->next = p1;
        p = p1;
    }
}

void print(LinkList L)
{
    LNode *p = L->next;
    if (p == L)
    {
        return;
    }
    while (p != L)
    {
        if (p->next != L)
            cout << p->data << " ";
        else
            cout << p->data << endl;
        p = p->next;
    }
}

void length(LinkList L)
{
    LNode *p = L->next;
    int res = 0;
    while (p != L)
    {
        p = p->next;
        res++;
    }
    cout << res << endl;
}

void empty_(LinkList L)
{
    if (L->next == L)
        cout << "yes" << endl;
    else
        cout << "no" << endl;
}

void three(LinkList L, int n)
{
    LNode *p = L;
    while (n--)
    {
        p = p->next;
    }
    cout << p->data << endl;
}

void zifu(LinkList L, char c)
{
    LNode *p = L->next;
    int res = 1;
    while (1)
    {
        if (p->data == c)
        {
            cout << res << endl;
            return;
        }
        p = p->next;
        res++;
    }
}

void push_(LinkList &L, char c, int n)
{
    LNode *p = L;
    n--;
    while (n--)
    {
        p = p->next;
    }
    LNode *p1;
    p1 = (LNode *)malloc(sizeof(LNode));
    p1->data = c;
    p1->next = p->next;
    p->next = p1;
}

void delete_(LinkList &L, int n)
{
    LNode *p = L;
    n--;
    while (n--)
    {
        p = p->next;
    }
    p->next = p->next->next;
}

int main()
{
    LinkList L;
    init(L);
    push(L);
    print(L);
    length(L);
    empty_(L);
    three(L, 3);
    zifu(L, 'a');
    push_(L, 'w', 4);
    print(L);
    delete_(L, 5);
    print(L);
    free(L);
    return 0;
}

栈和队列

顺序栈

#include <iostream>
#include <stdio.h>
using namespace std;
#define ll long long
#define MAX 10000007
#define MaxSize 1000000 // 定义栈中最大元素的个数
ll n;

typedef struct
{
    char data[MaxSize]; // 静态数组存放栈中元素,销毁栈时不必手动释放空间
    int top;            // 定义栈顶指针
} SqStack;

// 初始化栈
void InitStack(SqStack &S)
{
    S.top = -1;
}
void testStack()
{
    SqStack S; // 声明一个顺序栈(分配空间)
    InitStack(S);
}

// 判空
bool StackEmpty(SqStack S)
{
    if (S.top == -1)
        return true;
    else
        return false;
}

// 新元素入栈
bool Push(SqStack &S, char x)
{
    if (S.top == MaxSize - 1)
        return false;    // 栈满,报错
    S.data[++S.top] = x; // 指针先加1再让新元素入栈
    return true;
}

// 出栈操作
bool Pop(SqStack &S, char &x)
{
    if (S.top == -1)
        return false; // 栈为空
    x = S.data[S.top--];
    return true;
}

// 获取栈顶元素
bool GetTop(SqStack S, char &x)
{
    if (S.top == -1)
        return false; // 栈为空
    x = S.data[S.top];
    return true;
}

int main()
{
    // (1)初始化顺序栈S;
    SqStack S;
    InitStack(S);
    // (2)判断顺序栈S是否为空;
    if (StackEmpty(S))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (3)依次进栈元素a,b,c,d,e;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        char c;
        cin >> c;
        Push(S, c);
    }
    // (4)判断顺序栈S是否为空;
    if (StackEmpty(S))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (5)输出顺序栈长度;
    cout << S.top + 1 << endl;
    // (6)输出从栈顶到栈底的元素;
    for (int i = S.top; i >= 0; i--)
        cout << S.data[i] << " ";
    cout << endl;
    // (7)输出出栈序列;
    for (int i = S.top; i >= 0; i--)
    {
        char c;
        Pop(S, c);
        cout << c << " ";
    }
    cout << endl;
    // (8)判断顺序栈S是否为空;
    if (StackEmpty(S))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (9)释放顺序栈。
    return 0;
}

链栈

#include <iostream>
#include <stdio.h>
using namespace std;

typedef char ElemType; // 修改栈中存储什么类型的元素
typedef struct Lnode   // 新建链栈
{
    ElemType data;
    struct Lnode *next;
} Lnode, *Linkstack;

void init(Linkstack &s) // 初始化链栈
{
    s = NULL;
}

bool empty(Linkstack s) // 链栈判空
{
    return s == NULL;
}

void push(Linkstack &s, ElemType e) // 入栈
{
    Lnode *p = new Lnode;
    p->data = e;
    p->next = s;
    s = p;
}

void display(Linkstack s) // 输出栈中元素
{
    for (Lnode *p = s; p; p = p->next)
    {
        cout << p->data << " ";
    }
    cout << endl;
}

void pop(Linkstack &s) // 出栈
{
    if (empty(s))
        return;
    Lnode *p = s;
    s = s->next;
    delete p;
}

ElemType top(Linkstack s) // 输出栈顶
{
    return s->data;
}

int size(Linkstack s) // 输出栈中元素个数
{
    int n = 0;
    Lnode *p = s;
    while (p)
    {
        n++;
        p = p->next;
    }
    return n;
}

void destroy(Linkstack &s) // 释放栈
{
    Lnode *p = s;
    while (p)
    {
        Lnode *tmp = p;
        p = p->next;
        delete tmp;
    }
}

int main(void)
{
    Linkstack s;
    int n;
    cin >> n;
    // (1)初始化链栈S;
    init(s);
    // (2)判断链栈S是否为空;
    if (empty(s))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (3)依次进栈元素a,b,c,d,e;
    for (int i = 0; i < n; i++)
    {
        ElemType e;
        cin >> e;
        push(s, e);
    }
    // (4)判断链栈S是否为空;
    if (empty(s))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (5)输出链栈长度;
    cout << size(s) << endl;
    // (6)输出从栈顶到栈底的元素;
    display(s);
    // (7)输出出栈序列;
    while (!empty(s))
    {
        cout << top(s) << " ";
        pop(s);
    }
    cout << endl;
    // (8)判断链栈S是否为空;
    if (empty(s))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    // (9)释放链栈。
    destroy(s);
    return 0;
}

队列

#include <iostream>
#include <stdio.h>
using namespace std;
int n;

typedef struct LinkNode
{
    int data;
    struct LinkNode *next;
} LinkNode;

typedef struct
{
    LinkNode *front, *rear;
} LinkQueue;

// 初始化
void InitQueue(LinkQueue &Q)
{
    Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));
    Q.front->next = NULL;
}

// 判队空
bool IsEmpty(LinkQueue Q)
{
    if (Q.front == Q.rear)
    {
        printf("队空\n");
        return true;
    }
    else
    {
        printf("队不空\n");
        return false;
    }
}

// 入队
void EnQueue(LinkQueue &L, int x)
{
    LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
    s->data = x;
    s->next = NULL;
    L.rear->next = s; // 将新节点入队
    L.rear = s;       // 将尾指针后移
}

// 出队
bool DeQueue(LinkQueue &L, int &x)
{
    if (L.front == L.rear)
        return false;            // 空队
    LinkNode *p = L.front->next; // 查到队头元素
    x = p->data;
    L.front->next = p->next;
    if (p == L.rear)
    {
        L.front = L.rear;
    }
    free(p);
    return true;
}

// 输出队列
void PrintQueue(LinkQueue &L)
{

    LinkNode *p = L.front->next;
    while (p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main()
{
    LinkQueue p;
    InitQueue(p);
    while (cin >> n)
    {
        if (n >= 10 && n <= 99)
        {
            EnQueue(p, n);
        }
        else if (n == -1)
        {
            DeQueue(p, n);
        }
        else if (n == -2)
        {
            PrintQueue(p);
        }
        else if (n == -3)
            break;
    }
    return 0;
}

树与二叉树

二叉树的遍历

题目:二叉树的遍历问题
http://qdacm.openjudge.cn/dsweeks/33/

// 输入一棵二叉树的先序和中序遍历序列,输出其后序遍历序列。
//  思路:
//  前序序列的第一个值是根节点,将中序序列分成两部分。左边是左子树,右边是右子树
//  在左子树中,对应的前序序列的第二,是左子树的根节点,左边是其左子树,右边是其右子树
//  在右子树中,同理
//  当左子树为空,右子树为空时,结束
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
struct Node // 树的一个节点
{
    char data;
    Node *lChild, *rChild;
};

void postOrder(Node *root) // 树的后序遍历序列输出
{
    if (root == nullptr)
        return;

    postOrder(root->lChild);
    postOrder(root->rChild);
    cout << root->data;
}

int search(int num, char *in, int len) // 寻找中序序列中总根的位置
{

    for (int i = 0; i < len; i++)
        if (in[i] == num)
            return i;
    return -1;
}

Node *msn(char *pre, char *in, int len) // 递归构建树
{
    if (len <= 0)    // 当前中序遍历长度为零
        return NULL; // 树为空
    Node *root;
    root = new Node;
    int index = search(*pre, in, len);                                    // (先序遍历中的第一个数为根,当前中序序列,当前中序序列的长度)
    root->data = *pre;                                                    // 先序遍历中的第一个数为根
    root->lChild = msn(pre + 1, in, index);                               // 构建左树(先序遍历中的下一个数为根,整个中序序列,中序序列中对应左树的长度)
    root->rChild = msn(pre + index + 1, in + index + 1, len - index - 1); // 构建右树(先序遍历中的右半第一个数为根,中序序列右半,中序序列中对应右树的长度)
    return root;                                                          // 返回树的主根
}
int main()
{
    char *pre, *in;
    pre = new char[N];
    in = new char[N];
    cin >> pre;                      // 输入树的先序遍历,貌似这样写输入字符数组可以不用for
    cin >> in;                       // 输入树的中序遍历
    Node *root;                      // 树的根节点
    root = msn(pre, in, strlen(in)); // 构建出一棵树
    postOrder(root);                 // 输出后序遍历
    cout << endl;
    return 0;
}

中序遍历,非递归

#define MaxSize 1000
typedef struct BiTNode
{
	int data;
	struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
typedef struct
{
	BiTree data[MaxSize]; // 静态数组存放栈中元素,销毁栈时不必手动释放空间
	int top;			  // 定义栈顶指针
} SqStack;

// 初始化栈
void InitStack(SqStack &S)
{
	S.top = -1;
}
void testStack()
{
	SqStack S; // 声明一个顺序栈(分配空间)
	InitStack(S);
}

// 栈判空
bool IsEmpty(SqStack S)
{
	if (S.top == -1)
		return true;
	else
		return false;
}
// 新元素入栈
bool Push(SqStack &S, BiTree x)
{
	if (S.top == MaxSize - 1)
		return false;	 // 栈满,报错
	S.data[++S.top] = x; // 指针先加1再让新元素入栈
	return true;
}

// 出栈操作
bool Pop(SqStack &S, BiTree &x)
{
	if (S.top == -1)
		return false; // 栈为空
	x = S.data[S.top--];
	return true;
}
// 中序遍历,非递归
void InOrder(BiTree T)
{
	SqStack S;
	InitStack(S);			 // 初始化栈S
	BiTree p = T;			 // p作为遍历指针
	while (p || !IsEmpty(S)) // 栈不空或者p不空时进入循环
	{
		if (p) // 一路向左
		{
			Push(S, p);	   // 当前结点入栈
			p = p->lchild; // 左孩子不空就向左走
		}
		else // 出栈,并转向出栈结点的右子树
		{
			Pop(S, p); // 栈顶元素出栈
			// visit(p);//访问栈顶元素
			p = p->rchild; // 向右子树走,p赋值为当前结点的右孩子
		}
	}
}

并查集

题目:宗教信仰
http://bailian.openjudge.cn/practice/2524/

// 并查集
#include <iostream>
#include <stdio.h>
using namespace std;
#define ll long long
#define MAX 10000007
ll n, m, i, x, y, fa[1000000], ans, num = 1;

int find(int x)
{
    if (fa[x] == x)
        return x;
    return fa[x] = find(fa[x]);
}

void merge(int x, int y)
{
    x = find(x);
    y = find(y);
    if (x != y)
        fa[x] = y;
}

int main()
{
    while (cin >> n >> m)
    {
        if (n == 0 && m == 0)
        {
            break;
        }
        ans = n;
        for (int l = 1; l <= n; ++l)
        {
            fa[l] = l;
        }
        for (i = 1; i <= m; ++i)
        {
            cin >> x >> y;
            x = find(x);
            y = find(y);
            if (x != y)
            {
                merge(x, y);
                ans -= 1;
            }
        }
        cout << "Case " << num++ << ": " << ans << endl;
    }

    return 0;
}

哈夫曼树

题目:Huffman编码树
http://bailian.openjudge.cn/practice/4080/

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
#define ll long long
#define MAX 10000007
ll n, node[200], ans, t;
// 哈夫曼树,不断从森林中选取权值最小的两棵树组合成新树
int main()
{
    cin >> t;
    while (t--)
    {
        ans = 0;
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> node[i];
        sort(node + 1, node + n + 1);
        for (int i = n; i >= 2; i--)
        {
            sort(node + 1, node + n + 1);
            ans += (node[1] + node[2]);
            node[1] = (node[1] + node[2]);
            node[2] = 1000000000;
        }
        cout << ans << endl;
    }
    return 0;
}

KMP

#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;


const int N = 10000;
int cnt, ans[N];

int main()
{
    int n, m, q;
    cin >> n;
    while (n--)
    {
        string s;
        cin >> s >> m >> q;
        cnt = 0;
        for (int i = 0; i <= (int)s.size() - m; i++)
        {
            int sum = 0;
            for (int j = i; j < i + m; j++)
                sum += s[j] - 'a' + 1;
            if (sum == q)
                ans[cnt++] = i;
        }
        cout << cnt << endl;
        for (int i = 0; i < cnt; i++)
        {
            for (int j = ans[i]; j < ans[i] + m; j++)
                cout << s[j];
            cout << endl;
        }
    }

    return 0;
}

深度优先搜索与广度优先搜索

题目:图的深度优先遍历与广度优先遍历
http://qdacm.openjudge.cn/ds2024006/02/

#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <cstring>
#include <stdio.h>
using namespace std;

int mapp[1000][1000], num, flag[1000], ans[1000];
int m, n, idx;

void dfs(int x) // 深搜
{
	if (flag[x])
	{
		return;
	}
	flag[x] = 1;
	ans[++idx] = x;
	for (int i = m; i >= 1; i--)
	{
		if (mapp[x][i])
			dfs(i);
	}
}

void bfs(int x) // 广搜
{
	if (flag[x])
		return;
	queue<int> q;
	q.push(x);
	ans[++idx] = x;
	flag[x] = 1;
	while (!q.empty())
	{
		for (int i = m; i >= 1; i--)
		{
			if (!flag[i] && mapp[q.front()][i])
			{
				ans[++idx] = i;
				flag[i] = 1;
				q.push(i);
			}
		}
		q.pop();
	}
}

int main()
{
	cin >> m >> n;				 // m个顶点和n条边
	char c;						 // 接收无用字符
	for (int i = 1; i <= m; i++) // 存入m个点,作用存疑
	{
		cin >> c >> num;
	}
	for (int i = 1; i <= n; i++) // 存入n条边
	{
		int x, y;
		cin >> c >> x >> c >> y;
		mapp[x][y] = mapp[y][x] = 1; // 邻接矩阵存图
	}
	for (int i = 1; i <= m; i++)
	{
		dfs(i);
	}
	for (int i = 1; i <= idx; i++) // 输出深搜序列
	{
		cout << "v" << ans[i] << " ";
	}
	cout << endl;

	// 将存储信息的数组初始化防止造成干扰
	idx = 0;
	memset(ans, 0, sizeof(ans));
	memset(flag, 0, sizeof(flag));

	for (int i = 1; i <= m; i++)
	{
		bfs(i);
	}
	for (int i = 1; i <= idx; i++) // 输出广搜序列
	{
		cout << "v" << ans[i] << " ";
	}
	return 0;
}

拓扑排序

#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;

int n, m;
vector<vector<int>> ALgraph; // vector二维动态数组模拟邻接表,第一维为顶点表,第二维为边表
vector<int> ans, Indegree;   // ans中存放拓扑序列,Indegree存储各节点的入度
void TopsortbyQueue()
{
    priority_queue<int, vector<int>, greater<int>> q; // 递增优先队列,储存入度为0的顶点
    for (int i = 1; i <= n; ++i)
    { // 将入度为零的顶点放入队列中
        if (Indegree[i] == 0)
        {   
            q.push(i);
        }
    }
    while (!q.empty()) // 所有入度为零的点都被放进拓扑排序序列后结束
    {
        int u = q.top(); // 队头元素序号最小,拿出进行排序
        q.pop();
        ans.push_back(u);        // 队头放进拓扑排序序列
        for (int i : ALgraph[u]) // 遍历边表
        {
            Indegree[i]--;
            if (Indegree[i] == 0) // 入度为零入队
            {
                q.push(i);
            }
        }
    }
}

int main()
{
    cin >> n >> m;         // 顶点数n和弧数m
    ALgraph.resize(n + 1); // 一次性修改动态数组的空间大小,降低时间复杂度
    Indegree.resize(n + 1);
    for (int i = 1; i <= m; ++i) // 该条弧所关联的两个顶点编号
    {
        int u, v;
        cin >> u >> v;
        ALgraph[u].push_back(v); // 存入邻接表
        Indegree[v]++;           // 入度+1
    }
    TopsortbyQueue();
    for (int i : ans) // 输出拓扑排序后的序列
    {
        cout << "v" << i << " ";
    }
    return 0;
}

克洛斯卡尔最小生成树

题目:丛林中的路
http://bailian.openjudge.cn/practice/1251/

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;

int n, i, j, sum, cnt, fa[27], a;

struct E // 存储道路信息
{
    int a, b; // 起点和终点
    int w;    // 修路价格
} ed[10000];

bool cmp(E m, E n) // 结构体排序sort参数,以价格为关键字递减
{
    return m.w < n.w;
}

int find(int x) // 并查集查找x的父节点
{
    if (fa[x] == x)
        return x;
    return fa[x] = find(fa[x]);
}

int main()
{
    while (cin >> n) // 村落数目n
    {
        sum = 0;
        cnt = 0;
        a = 0;
        int index = 0;
        if (n == 0)
            break;

        while (n-- > 1)
        {
            char x;
            int k;
            cin >> x >> k;          // x为村号,k为与该村庄连接的其他村庄个数
            a = x - 'A' + 1;        // 字母村号转化为数字编号
            for (j = 0; j < k; j++) // k个村庄的编号以及各自到起始村庄的道路维修费用
            {
                ed[++index].a = a; // 从1开始
                char y;
                cin >> y; // 村号
                ed[index].b = y - 'A' + 1;
                int w;
                cin >> w; // 道路价格
                ed[index].w = w;
            }
            // n--;
        }
        // 初始化并查集,所有点的父节点是它自己
        for (i = 1; i <= 27; i++)
            fa[i] = i;

        sort(ed + 1, ed + index + 1, cmp); // 将所有路按照价格从小到大排序

        for (i = 1; i <= index; i++) // 克洛斯卡尔构造最小生成树
        {
            int m = find(ed[i].a);
            int n = find(ed[i].b);
            if (m != n)
            {
                fa[m] = n;
                sum += ed[i].w;
                cnt++;
            }
        }
        cout << sum << endl;
    }
    return 0;
}

弗洛伊德最短路

题目:兔子与樱花
http://qdacm.openjudge.cn/ds2024006/04/

#include <iostream>
#include <map>
#include <cstring>
#include <stdio.h>
using namespace std;
#define ll long long
#define MAX 10000007

map<string, int> map1;
map<int, string> map2;
ll step[35][35];
ll point[35][35];
ll p, q, r, d;
string t1, t2;

// 弗洛伊德最短路
void floyd()
{
    for (int k = 0; k < p; k++)
    {
        for (int i = 0; i < p; i++)
        {
            for (int j = 0; j < p; j++)
            {
                if (step[i][j] > step[i][k] + step[k][j]) // 点k与i,j任意一点不相连时为false,不是目前最短路径时为false,i,j不相连时为false
                {
                    step[i][j] = step[i][k] + step[k][j];
                    point[i][j] = point[i][k];
                }
            }
        }
    }
}

int main()
{
    // dist[i][j]表示i到j的最短距离,距离极大表示两个地点不连通
    for (int i = 0; i < 35; i++)
    {
        for (int j = 0; j < 35; j++)
        {
            step[i][j] = MAX;
        }
        step[i][i] = 0; // 一个地点到自身的距离为零
    }

    // point[i][j]表示从i到j的最短路线中从i出发的下一个结点,记录最短路径
    for (int i = 0; i < 35; i++)
    {
        for (int j = 0; j < 35; j++)
        {
            point[i][j] = j;
        }
    }

    cin >> p; // 存入p个地点
    for (int i = 0; i < p; i++)
    {
        cin >> t1;
        map1[t1] = i; // 将地名映射为数字编号
        map2[i] = t1;
    }

    cin >> q;
    for (int i = 0; i < q; i++) // 存入两个点之间的距离
    {
        cin >> t1 >> t2 >> d;
        step[map1[t1]][map1[t2]] = step[map1[t2]][map1[t1]] = d;
    }

    floyd(); // 弗洛伊德求最短路

    cin >> r; // R次询问最短路径
    while (r--)
    {
        cin >> t1 >> t2;
        if (t1 != t2)
        {
            int x = point[map1[t1]][map1[t2]];
            cout << t1 << "->(" << step[map1[t1]][x] << ")->";
            while (x != map1[t2])
            {
                cout << map2[x] << "->(" << step[x][point[x][map1[t2]]] << ")->";
                // 更新下一结点
                x = point[x][map1[t2]];
            }
        }
        cout << t2 << endl;
    }
    return 0;
}

排序

快速排序

// 使小于基准元素的数字在左,大于基准元素的数字在右
int Partion(int a[], int low, int high) // low 和 high 为指向高位和低位的指针
{
	int mid = a[low];  // 取第一个元素为基准元素
	while (low < high) // 保证低位指针不会大于高位指针
	{
		while (low < high && a[high] >= mid) // 如果高位指针指向的数字大于基准元素,就跳过
			high--;
		a[low] = a[high];					 // 小于基准元素的数字移到前面
		while (low < high && a[high] >= mid) // 如果低位指针指向的数字小于基准元素,就跳过
			low++;
		a[high] = a[low]; // 大于基准元素的数字移到后面
	}
	a[low] = mid; // 将基准元素放中间
	return low;	  // 返回基准元素的最终位置
}

// 快速排序算法
void QuickSort(int a[], int low, int high)
{
	if (low < high) // 保证低位指针不会大于高位指针,否则跳出递归
	{
		int midSign = Partion(a, low, high); // 将元素划分为两部分
		QuickSort(a, low, midSign + 1);		 // 对左半部分递归划分
		QuickSort(a, midSign - 1, high);	 // 对右半部分递归划分
	}
}

直接插入排序

// 直接插入排序
void InsertSort(int a[], int n)
{
	int i, j;
	for (i = 2; i <= n; i++) // 从前往后检查
	{
		if (a[i] < a[i - 1]) // 该元素小于前驱元素
		{
			a[0] = a[i];					  // 该元素暂存0号位置
			for (j = i - 1; a[0] < a[j]; j--) // 比该元素大的元素都往后移动
			{
				a[j + 1] = a[j];
			}
			a[j + 1] = a[0]; // 把该元素填回空位
		}
	}
}

希尔排序

// 希尔排序
void ShellSort(int a[], int n)
{
	int dk, i, j;						   // dk为分组时使用的增量
	for (dk = n / 2; dk >= 1; dk = dk / 2) // 使增量大小不断降低
	{
		for (i = dk + 1; i <= n; i++) // 对每个分组进行直接插入排序
		{
			if (a[i] < a[i - dk])
			{
				a[0] = a[i];
				for (j = i - dk; j > 0 && a[0] < a[j]; j -= dk)
				{
					a[j + dk] = a[j];
				}
				a[j + dk] = a[0];
			}
		}
	}
}

简单选择排序

void selectSort(int arr[], int len)
{
	int i, j;
	int min; //待排序数组中最小值的下标
	int tmp;
	for (i = 0; i < len - 1; ++i)//i = 0,第一次待排数组为所有数
	{   
		min = i;
		for (j = i + 1; j < len; ++j)
		{
			if (arr[j] < arr[min])
			{
				min = j;//
			}
		}
		//将arr[i]与arr[min]交换位置
		tmp = arr[i];
		arr[i] = arr[min];
		arr[min] = tmp;
	}
}
void selectShow(int arr[], int len)
{
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = {59,26,245,21,6,10,16};
	int len = sizeof(arr) / sizeof(arr[0]);
	selectShow(arr, len);
	selectSort(arr, len);
	selectShow(arr, len);
	return 0;
}

冒泡排序

#include <iostream>
using namespace std;
template<typename T> //整数或浮点数皆可使用,若要使用类(class)或结构体(struct)时必须重载大于(>)运算符
void bubble_sort(T arr[], int len) {
        int i, j;
        for (i = 0; i < len - 1; i++)
                for (j = 0; j < len - 1 - i; j++)
                        if (arr[j] > arr[j + 1])
                                swap(arr[j], arr[j + 1]);
}
int main() {
        int arr[] = { 61, 17, 29, 22, 34, 60, 72, 21, 50, 1, 62 };
        int len = (int) sizeof(arr) / sizeof(*arr);
        bubble_sort(arr, len);
        for (int i = 0; i < len; i++)
                cout << arr[i] << ' ';
        cout << endl;
        float arrf[] = { 17.5, 19.1, 0.6, 1.9, 10.5, 12.4, 3.8, 19.7, 1.5, 25.4, 28.6, 4.4, 23.8, 5.4 };
        len = (float) sizeof(arrf) / sizeof(*arrf);
        bubble_sort(arrf, len);
        for (int i = 0; i < len; i++)
                cout << arrf[i] << ' '<<endl;
        return 0;
}

杂项

求树的叶子结点个数

int leafsum(BiTree T)
{
	if (T == NULL)
		return 0;
	else if (T->lchild == NULL && T->rchild == NULL)
		return 1;
	return (leafsum(T->lchild) + leafsum(T->rchild));
}

求二叉树的宽度

int count[100];
int MAX = -1;

void FindWidth(BitNode T, int k)
{
	if (T == NULL)
		return;
	count[k]++;
	if (MAX < count[k])
		MAX = count[k];
	FindWidth(T->lchild, k + 1);
	FindWidth(T->rchild, k + 1);
}

// MAX即为所求宽度

求二叉树的高度

int BTdepth(BiTree T)
{				   // 求树的高度depth
	if (T != NULL) // 空树的高度为零
		return 0;
	ldepth = BTdepth(T->lchild); // 求左孩子的高度
	rdepth = BTdepth(T->rchild); // 求右孩子的高度
	if (ldepth > rdepth)
	{
		ldepth = ldepth + 1;
		// 树的高度为最大高度的子树加个根结点
		return ldepth;
	}
	else
	{
		rdepth = rdepth + 1;
		return rdepth;
	}
}

单链表逆置

void ListReverse(LinkList &L)
{
    LNode *begin = L->next;
    LNode *end = L->next->next;
    while (end != NULL)
    {
        begin->next = end->next;
        end->next = L->next;
        L->next = end;
        end->next = begin->next;
    }
}
posted @ 2024-06-17 18:57  你这过氧化氢掺水了  阅读(70)  评论(0编辑  收藏  举报