与算法设计有关的几种基础算法的实现汇总
注:代码中是在网上搜集,然后自己对其中部分内容进行修改后得到的
1.改进的归并排序(使用静态链表实现)
#include<iostream>
#include<random>
#include<time.h>
#include<iostream>
#define max 100000
using namespace std;
#define n 10000
int LINK[n];
void Merge(int *a, int p, int q, int r)
{
int n1 = q - p + 1; //左部分的的元素个数
int n2 = r - q; //右边部分
int i, j, k;
int *L = new int[n1 + 1];
int *R = new int[n2 + 1];
for (i = 0; i < n1; i++)
L[i] = a[p + i];
for (j = 0; j < n2; j++)
R[j] = a[q + j + 1];
L[n1] = max;
R[n2] = max;
for (i = 0, j = 0, k = p; k <= r; k++)
{
if (L[i] <= R[j])
a[k] = L[i++];
else
a[k] = R[j++];
}
delete[]L;
delete[]R;
}
void MergeSort(int *a, int l, int r)
{
if (l < r)
{
int m = (l + r) / 2;
MergeSort(a, l, m);
MergeSort(a, m + 1, r);
Merge(a, l, m, r);
}
}
void quick_sort(int *a, int left, int right) //left和right为索引值
{
int temp; //存储每次选定的基准数(从最左侧选基准数)
int t;
int initial = left;
int end = right;
temp = a[left];
//***必须有这一部分***//
if (left > right) //因为在递归过程中有减1加1的情况,当其越界时,直接return,不返回任何值,即结束当前程序块
return;
while (left != right) //此时左右index在移动中,若left==right,则跳出循环,将基数归位
{
while (a[right] >= temp && left < right) //直到找到小于基准数的值为准
right--;
while (a[left] <= temp && left < right) //找到大于基准值
left++;
if (left < right) //交换左右两侧值,当left=right时,跳出外层while循环
{
t = a[right];
a[right] = a[left];
a[left] = t;
}
}
a[initial] = a[left];
a[left] = temp; //将基准放到指定位置
//递归处理归位后的基准数的左右两侧
quick_sort(a, initial, left - 1); //此时left=right
quick_sort(a, left + 1, end);
}
void show(int*a, int len) {
for (int i = 0; i < len; i++)
cout << a[i] << " ";
}
void copy(int*a, int*b, int len) {
for (int i = 0; i < len; i++)
b[i] = a[i];
}
void Merge_(int& p, int q, int r, int* A)
{
int i = q, j = r, k = 0;
while (i != 0 && j != 0)
{
if (A[i] <= A[j])
{
LINK[k] = i;
k = i;
i = LINK[i];//找到下一个元素
}
else
{
LINK[k] = j;
k = j;
j = LINK[j];
}
}
if (i == 0)//结束
LINK[k] = j;
else
LINK[k] = i;
p = LINK[0];//开始的地方
}
void InsertionSort(int low, int high, int& p, int*A)
{
int a[n + 1], b[n + 1], k = 0;
for (int i = low; i <= high; ++i)
a[A[i]] = i;
for (int i = low; i <= high; ++i)
b[i] = A[i];
sort(b + low, b + high + 1);//将b中元素排序
for (int i = low; i <= high; ++i)
{
LINK[k] = a[b[i]];
k = a[b[i]];
}
p = LINK[0];
}
void MergeSort_(int low, int high, int& p, int*A)
{
if (high - low + 1 < 15)
InsertionSort(low, high, p, A);
else
{
int mid = (low + high) / 2;
int q = 0, r = 0;
MergeSort_(low, mid, q, A);
MergeSort_(mid + 1, high, r, A);
Merge_(p, q, r, A);
}
}
int main()
{
int* arr=new int[n];
int* arr2 = new int[n];
int* arr3= new int[n];
for (int i = 0; i < n; i++)
{
LINK[i] = 0;
}
double dur;
clock_t start, end;
srand((unsigned int)time(NULL));
for (int i = 0; i < n; i++)
{
arr[i] = rand() % n;
;
}
copy(arr, arr2, n);
for (int i = 1; i <= n; i++)
{
arr3[i] = rand() % n;
}
cout <<"数据个数"<<n<< endl;
//快速排序
start = clock();
quick_sort(arr, 0, n - 1);
end = clock();
dur = (double)(end - start) / CLOCKS_PER_SEC;
cout << "快速排序:" << dur << endl;
//归并排序
start = clock();
MergeSort(arr2, 0, n - 1);
end = clock();
dur = (double)(end - start) / CLOCKS_PER_SEC;
cout << "归并排序:" << dur << endl;
//该进后的归并排序
int M = n;
int p = 0;
start = clock();
MergeSort_(1, M, p, arr3);
end = clock();
dur = (double)(end - start) / CLOCKS_PER_SEC;
/*
for (int i = p; i != 0; i = LINK[i])
cout << arr3[i] << " ";
*/
cout << "改进的归并排序:" << dur << endl;
cout << endl;
return 0;
}
2.Prim算法实现
#include<iostream>
#include<vector>
using namespace std;
#define MAX 100
#define MAXCOST 100
int graph[MAX][MAX];
struct edge {
int x, y;
int w;
edge(int a, int b, int c) {
x = a;
y = b;
w = c;
}
};
vector<edge> E;//用于保存边
vector<edge> result;//保存最终的边
int flag(int * a,int n)
{
int flag = 1;
for (int i = 2; i <= n; i++)
{
if (a[i] == 0)
{
flag = 0;
break;
}
}
return flag;
}
edge min(int * a) {
int size = E.size();
for (int j = 0; j < size; j++) {
if (a[E[j].x] && a[E[j].y]) {//两个端点都被使用过
E[j].w = MAXCOST;
}
}
edge min=E[0];
int j=0;
for (int i = 1; i < size; i++) {
if (min.w >= E[i].w) {
min = E[i];
j = i;
}
}
E[j].w = MAXCOST;//将其标记为已占用
return min;
}
void Prim(int graph[][MAX], int n)//二维数组作为参数如何使用?
{
int state[MAX];//存放状态
state[1] = 1;
for (int i = 2; i <= n; i++) {//初始化
state[i] = 0;
if(graph[1][i]!=MAXCOST)
{
edge e = edge(1, i, graph[1][i]);
E.push_back(e);//加入边
}
}
while (!flag(state,n))//迭代,让树生长
{
edge tep = min(state);
result.push_back(tep);//将边导入数据
int add;
if (state[tep.x])
add = tep.y;
else
add = tep.x;
state[add] = 1;
for (int i = 2; i <= n; i++) {//初始化
if (graph[add][i] != MAXCOST)
{
edge e = edge(add, i, graph[add][i]);
E.push_back(e);//加入边
}
}
}
}
int main()
{
int m, n, x, y, cost;
cout << "请输入节点数目和边的数目:" << endl;
cin >> m >> n;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= m; j++)
graph[i][j] = MAXCOST;
cout << "请输入边" << endl;
for (int k = 1; k <= n; k++)
{
cin >> x >> y >> cost;
graph[x][y] = graph[y][x] = cost;//无向图
}
Prim(graph, m);
cout << "最小生成树" << endl;
int sum = 0;
for (int i = 0; i < result.size(); i++)
{
cout << result[i].x << " " << result[i].y << " " << result[i].w << endl;
sum += result[i].w;
}
cout<<"权值: "<<sum<<endl;
return 0;
}
3.Kruskal算法实现
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100
#define M 1000
int n, m, u, v, w;
int father[N];
struct Edge {
int u, v, w;
}edge[M];
Edge result[M];
int cnt;
void addEdge(int u, int v, int w) {
edge[cnt++] = Edge{ u,v,w };
}
bool cmp(Edge a, Edge b) {//由小到大排序
return a.w < b.w;
}
int find(int x) {
if (father[x] == x)
return x;
else
return find(father[x]);
//return father[x] == x ? x : father[x] = find(father[x]);//递归寻找父亲
}
int Kruskal() {
int sum = 0;
int c = 0;
for (int i = 0; i <= n; i++) {//初始化
father[i] = i;
}
sort(edge, edge + cnt, cmp);
for (int i = 0; i < cnt; i++) {
int u = edge[i].u;
int v = edge[i].v;
int w = edge[i].w;
int fa = find(u);
int fb = find(v);
if (fa != fb) {
sum += w;
father[fa] = fb;
result[c] = edge[i];
c++;
}
if (c == n - 1) {
break;
}
}
if (c < n - 1) {
//不连通
return -1;
}
return sum;
}
int main(void) {
cout << "请输入点和边的个数" << endl;
cin >> n >> m;
cnt = 0;
cout << "请输入边的信息" << endl;
while (m--) {
cin >> u >> v >> w;
addEdge(u, v, w);
}
cout << "最小生成树" << endl;
int sum = Kruskal();
for (int i = 0; i < n - 1; i++) {
cout << result[i].v << " " << result[i].u << " " << result[i].w << endl;
}
cout << "权值: " << sum << endl;
return 0;
}
4.Dijkstra算法实现
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 100
#define MAXCOST 100000
int path[MAX];//保存前驱结点
int Graph[MAX][MAX];//保存图
int state[MAX];//保存结点状态
int dist[MAX];
void Dijkstra(int G[][MAX], int v, int n)//输入源结点
{
int u = v;
for (int i = 0; i < n; i++)
{
state[i] = 0;
dist[i] = G[v][i];
if (dist[i] < MAXCOST)
{
path[i] = v;
}
else
{
path[i] = -1;
}
}
state[v] = 1;
for (int i = 0; i < n; i++)
{
int min = MAXCOST;
for (int j = 0; j < n; j++)
{
if (state[j] == 0 && dist[j] < min)//dist中找出最小值
{
u = j;
min = dist[j];
}
}
state[u] = 1;
for (int j = 0; j < n; j++)//更新
{
if (state[j] == 0 && dist[u] + G[u][j] < dist[j])
{
dist[j] = dist[u] + G[u][j];
path[j] = u;
}
}
}
}
void show( int v,int n) {
for (int i = 0; i < n; i++) {
if (i != v&&dist[i]<MAXCOST) {
cout << v << "->" << i << "最短距离 " << dist[i] << endl;
cout << "路径 " ;
int j = i;
while (path[j]!=-1)
{
cout << j << "<-";
j = path[j];
}
cout << v;
cout << endl << endl;;
}
}
}
int main() {
int n, m;
int x, y, cost;
cout << "请输入结点数和边数" << endl;
cin >> n >> m;
for (int i = 0; i <= m; i++)
for (int j = 0; j <= m; j++)
Graph[i][j] = MAXCOST;//初始化
cout << "请输入边" << endl;
for (int k = 1; k <= m; k++)
{
cin >> x >> y >> cost;
Graph[x][y]= cost;//有向图
}
Dijkstra(Graph, 0, n);
show(0, n);
}
5.Floyd算法
#include <iostream>
#include <stack>
#define MAX 1000
#define MAX_VERTEX 20
using namespace std;
struct Graph
{
int *edges[MAX];
int Vcount, Ecount;
};
void Init(Graph *graph) {
cout << "请输入顶点数和边数" << endl;
cin >> graph->Vcount >> graph->Ecount;
for (int row = 1; row <= graph->Vcount; row++) {
for (int col = 1; col <= graph->Vcount; col++) {
graph->edges[row][col] = MAX;
}
}
cout << "请输入边" << endl;
int row, col, iWeight;
for (int i = 1; i <= graph->Ecount; i++) {
cin >> row >> col >> iWeight;
graph->edges[row][col] = iWeight;
}
}
void Floyd(Graph *graph, int **path) {
for (int i = 1; i <= graph->Vcount; i++) {
for (int j = 1; j <= graph->Vcount; j++) {
path[i][j] = i;
}
}//初始化路径表
for (int k = 1; k <= graph->Vcount; k++) {
for (int i = 1; i <= graph->Vcount; i++) {
for (int j = 1; j <= graph->Vcount; j++) {
if (graph->edges[i][k] + graph->edges[k][j] < graph->edges[i][j]) {
graph->edges[i][j] = graph->edges[i][k] + graph->edges[k][j];
path[i][j] = path[k][j];
}
}
}
}
}
void Show(Graph *graph, int **path) {
for (int i = 1; i <= graph->Vcount; i++) {
for (int j = 1; j <= graph->Vcount; j++) {
if (i != j) {
cout << i << "->" << j << "\t";
if (graph->edges[i][j] == MAX) {
cout << "无路径" << "\t" << endl;
}
else {
cout << graph->edges[i][j] << "\t";
stack<int> stackVertices;// 利用栈来实现
int k = j;
do
{
k = path[i][k];
stackVertices.push(k);
} while (k != i);
cout << stackVertices.top();
stackVertices.pop();
int len = stackVertices.size();
for (int i = 0; i < len; i++)
{
cout << " -> " << stackVertices.top();
stackVertices.pop();
}
cout << " -> " << j << endl;
}
}
}
}
}
int main()
{
int *path[MAX];
for (int i = 0; i < MAX; i++) {
path[i] = new int[MAX];
}
Graph graph;
for (int i = 0; i < MAX; i++) {
graph.edges[i] = new int[MAX];
}
Init(&graph);//初始化数据
Floyd(&graph, path);
Show(&graph, path);//展示数据
system("pause");
return 0;
}
6.动态规划求解多端图问题
#include<iostream>
using namespace std;
#define MAX 1000
void FGRAPH(int N, int k, int **P, int **cost, int** C, int *path)
{
int i, j, t ;
int m;
int point;
point = P[k][0];
for (i = k - 1; i >= 1; i--)//阶段 向前地推
{
j = 0;//i阶段的状态
while (P[i][j] != 0)//保存点的编号
{
m = 0;//i+1阶段的状态
cost[i][j] = MAX;
if (C[P[i][j]][point] == MAX) //C是用于计算距离
{
while (P[i + 1][m] != 0)
{
if (C[P[i][j]][P[i + 1][m]] != MAX)//两个点之间有路径
{
if (cost[i][j] > (cost[i + 1][m] + C[P[i][j]][P[i + 1][m]]))
{
cost[i][j] = cost[i + 1][m] + C[P[i][j]][P[i + 1][m]];//取最小值
path[P[i][j]] = P[i + 1][m];//替换选择,保存路径
}
}
m++;
}
}
else//初始化
{
while (P[i + 1][m] != 0)
{
if (cost[i][j] > (cost[i + 1][m] + C[P[i][j]][P[i + 1][m]]))
{
cost[i][j] = cost[i + 1][m] + C[P[i][j]][P[i + 1][m]];
path[P[i][j]] = P[i + 1][m];
}
m++;
}
}
j++;
}
}
cout << "符合条件的点为:" << endl;
t = 0;
path[t] = 1;
cout << path[t] << " ";
t = path[t];
while (t < N)
{
cout << path[t] << " ";
t = path[t];
}
cout << endl << "最短距离为:";
cout << cost[i + 1][0] << endl;
}
void Init(int N, int k, int** P, int **C)//k 表示有几个阶段 初始化多段图 C存储多段图信息
{
int X;
int i, j;
cout << "输入边的信息:" << endl;
cin >> i;
while (i != 0)
{
cin >> j;
cin >> C[i][j];
cin >> i;
}
cout << "输入每个阶段的信息:" << endl;
for (i = 1; i <= k; i++)// 1到k
{
cout << "输入第" << i << "阶段的状态的点数:";
cin >> X;
cout << "点的信息分别为:";
for (j = 0; j < X; j++)
{
cin >> P[i][j];//保存点的状态
}
}
}
int main(int argc, char *argv[])
{
int N, k;
int i, j;
int **C, **P, **cost;//C:边的长度,P;每个阶段的状态;cost:记录每个阶段的状态中的点到终点的距离
int *path;//输出点
cout << "输入点的个数:";
cin >> N;
cout << "输入阶段数:";
cin >> k;
C = new int*[N + 1];
//初始化
for (i = 0; i < N + 1; i++)
{
C[i] = new int[N + 1];
for (j = 0; j < N + 1; j++)
{
C[i][j] = MAX;
}
}
P = new int*[N + 1];
for (i = 0; i < N + 1; i++)
{
P[i] = new int[N + 1];
memset(P[i], 0, sizeof(int)*(N + 1));//初始化
}
cost = new int *[N + 1];
for (i = 0; i < N + 1; i++)
{
cost[i] = new int[N + 1];
for (j = 0; j < N + 1; j++)
{
cost[i][j] = 0;
}
}
path = new int[N + 1];
memset(path, 0, sizeof(int)*(k + 1));
Init(N, k, P, C);
//删除
FGRAPH(N, k, P, cost, C, path);
delete[]path;
for (i = 0; i < N + 1; i++)
{
delete[]C[i];
}
delete[]C;
for (i = 0; i < N + 1; i++)
{
delete[]P[i];
}
delete[]P;
for (i = 0; i < N + 1; i++)
{
delete[]cost[i];
}
delete[]cost;
return 0;
}