目錄
- 線性表
- 順序表
- 單連結串列
- 迴圈單連結串列
- 棧和佇列
- 順序棧
- 鏈棧
- 佇列
- 樹與二叉樹
- 二叉樹的遍歷
- 並查集
- 哈夫曼樹
- 串
- 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;
}