資料結構程式碼常用模板

你这过氧化氢掺水了發表於2024-06-17

目錄
  • 線性表
    • 順序表
    • 單連結串列
    • 迴圈單連結串列
  • 棧和佇列
    • 順序棧
    • 鏈棧
    • 佇列
  • 樹與二叉樹
    • 二叉樹的遍歷
    • 並查集
    • 哈夫曼樹
    • KMP
    • 深度優先搜尋與廣度優先搜尋
    • 拓撲排序
    • 克洛斯卡爾最小生成樹
    • 弗洛伊德最短路
  • 排序
    • 快速排序
    • 直接插入排序
    • 希爾排序
    • 簡單選擇排序
    • 氣泡排序

線性表

順序表

#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;
}

並查集

題目:宗教信仰
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;
}

排序

快速排序

void QuickSort(int array[], int low, int high) {
    int i = low; 
    int j = high;
    if(i >= j) {
        return;
    }
 
    int temp = array[low];
    while(i != j) {
        while(array[j] >= temp && i < j) {
            j--;
        }
	while(array[i] <= temp && i < j) {
            i++;
        }
	if(i < j) {
            swap(array[i], array[j]);
        }
    }
 
    //將基準temp放於自己的位置,(第i個位置)
    swap(array[low], array[i]);
    QuickSort(array, low, i - 1);
    QuickSort(array, i + 1, high);
}

直接插入排序

#include<bits/stdc++.h>

using namespace std;

void InsertSort(int a[],int l)
{
    int temp;
    int j;
    for(int i=1;i<l;i++)
    {
        if(a[i]<a[i-1])
        {
            temp=a[i];
            for(j=i-1;j>=0&&temp<a[j];j--)
            {
                a[j+1]=a[j];
            }
            a[j+1]=temp;

        }
        for(int k=0;k<l;k++)
            cout<<a[k]<<" ";
        cout<<endl;

    }
}


int main()
{
    int a[10]={2,5,8,3,6,9,1,4,7};
    int b[10]={1,2,3,4,5,6,7,8,9};
    int len=9;
    InsertSort(a,len);
    return 0;
}

希爾排序

template<typename T>
void shell_sort(T array[], int length) {
    int h = 1;
    while (h < length / 3) {
        h = 3 * h + 1;
    }
    while (h >= 1) {
        for (int i = h; i < length; i++) {
            for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
                std::swap(array[j], array[j - h]);
            }
        }
        h = h / 3;
    }
}

簡單選擇排序

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;
}

相關文章