一般的に使用されるアルゴリズム コード テンプレートの概要

以下のコンテンツは、対応するアルゴリズムの便利で使いやすいテンプレートを提供するか、特定の関数を関数化し、パラメーターを渡して直接呼び出すだけです。アルゴリズムの詳細な証明は提供されていません。ほとんどのアルゴリズムは Java で書かれており、他の言語に変換できます。長すぎる内容は別ブログにまとめ、対応する練習問題もブログ内で提供します。継続的に更新中...

目次

クイックソート

マージソート

ヒープソート

プレフィックスの和と差(1次元、2次元)

そしてコレクションを検索してください

整数二分、浮点二分

配列から重複した要素を削除する (ダブルポインター)

最大公約数を見つける

最小公倍数を見つける

素数を見つける (オイラーふるい)

高精度加算(C++)

高精度減算(C++)

高精度乗算(C++)

高精度除算(C++)

動的プログラミングのナップザック問題

パターンマッチングアルゴリズム KMPアルゴリズム

最小スパニング ツリー (無向グラフ) のプリム アルゴリズム

最小スパニング ツリー (無向グラフ) の Kruskal アルゴリズム

単一ソース最短経路のダイクストラ アルゴリズム (無向グラフ)

単一ソース最短パスのベルマンフォード アルゴリズム (有向グラフ)

複数ソース最短経路のフロイド アルゴリズム (有向グラフ)

warshall アルゴリズムは、グラフが接続されているかどうかを決定します (隣接行列はグラフを保存します)。


クイックソート

クイックソートJavaコードテンプレート

マージソート

マージソートJavaコードテンプレート

ヒープソート

ヒープのソートとシミュレートされたヒープの Java コード テンプレート

プレフィックスの和と差(1次元、2次元)

プレフィックス合計および差分コード テンプレート

そしてコレクションを検索してください

Javaコードテンプレートを検索します

整数二分、浮点二分

整数の二等分および浮動小数点の二等分コード テンプレート

配列から重複した要素を削除する (ダブルポインター)

public static void main(String args[]) {
		int[] nums = { 1, 1, 2, 2, 2, 3, 4, 4, 5, 6, 7 };
		int j = 0;

		for (int i = 0; i < nums.length; i++) {//去除数组当中重复的元素
			if (i == 0 || nums[i] != nums[i - 1])
				nums[j++] = nums[i];
		}

		for (int i = 0; i < j; i++)
			System.out.print(nums[i] + " ");//输出:1 2 3 4 5 6 7 
	}

最大公約数を見つける

簡単な方法

public static int gcd(int a, int b) {// 最大公约数朴素写法,传入两个数,返回最大公约数。
		while (b != 0) {
			int temp = a % b;
			a = b;
			b = temp;
		}
		if (a < 0)
			return -a;
		return a;
}

 再帰的書き込み

public static int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

最小公倍数を見つける

public static int gbs(int n, int m) {//传入两个数,得到两个数的最小公倍数

    int temp = Math.max(n, m);//求得这两个数的较大值
    for (int i = temp; ; i++) {//从较大值开始遍历
        if (i % n == 0 && i % m == 0)
            return i;
    }

}

素数を見つける (オイラーふるい)

public static int[] Prime(int n) {// 欧拉筛求素数,传入参数n表示范围的最大值
		int[] prime = new int[100010];// 能够存放的素数个数
		boolean[] bool = new boolean[100010];
		int count = 0;// 记录素数个数
		for (int i = 2; i <= n; i++) {
			if (bool[i] == false) {
				prime[count++] = i;
				bool[i] = true;
			}
			for (int j = 0; j < count; j++) {
				if (i * prime[j] > n)
					break;
				bool[i * prime[j]] = true;
				if (i % prime[j] == 0)
					break;
			}
		}
		System.out.printf("0~%d范围内的素数个数为:%d\n", n, count);// 输出个数
		return prime;
	}

高精度加算(C++)

Java と Python には高い精度は必要ありません。Java は BigInteger を使用しますが、Python の方が便利です。

vector<int> add(string a, string b){//传入两个数的字符串形式,返回之和。 
	 	
		if (a.length() < b.length()) return add(b, a);

        int t = 0;
		vector<int> A, B, c;
	    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
	    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

	    
	    for (int i = 0; i < A.size(); i ++ ){
	        t += A[i];
	        if (i < B.size()) t += B[i];
	        C.push_back(t % 10);
	        t /= 10;
	    }

	    if (t) C.push_back(t);
	    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
	    return C;
	}

高精度減算(C++)

高精度減算では正負の符号の判定が必要となるため、少し複雑になります。

bool cmp(vector<int> &A, vector<int> &B)//正负号判断
{
    if (A.size() != B.size()) return A.size() > B.size();

    for (int i = A.size() - 1; i >= 0; i -- )
        if (A[i] != B[i])
            return A[i] > B[i];

    return true;
}

vector<int> sub(vector<int> &A, vector<int> &B)//传入数字,返回差。
{
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;
        else t = 0;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

int main()
{
    string a, b;
    vector<int> A, B;
    cin >> a >> b;//输入两个字符串形式的数组,返回其差
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

    vector<int> C;

    if (cmp(A, B)) C = sub(A, B);//根据正负号的不同选择不同的相减方式
    else C = sub(B, A), cout << '-';

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
    cout << endl;

    return 0;
}

高精度乗算(C++)

2 つの数値を高精度に乗算すると、通常は 1 つの数値のみが非常に大きくなります。

vector<int> mul(string a, long b){//传入一个数的字符串形式和另一个数,返回其乘积。 
	
	vector<int> A, c;
    int t = 0;
    
    for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
	
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
	//for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
    return C;
}

高精度除算(C++)

vector<int> div(string a, int b, int &r)//传入 
{
	vector<int> A, c;
	r = 0;//记录余数 
	
	for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
    
    for (int i = A.size() - 1; i >= 0; i -- )
    {
        r = r * 10 + A[i];
        C.push_back(r / b);
        r %= b;
    }
    reverse(C.begin(), C.end());
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    printf("\n余数为:%d\n",r); 
    return C;
}

動的プログラミングのナップザック問題

動的計画法ナップザック問題のまとめ

パターンマッチングアルゴリズム KMPアルゴリズム

KMP アルゴリズムの原理とコード分析の図解

最小スパニング ツリー (無向グラフ) のプリム アルゴリズム

最小スパニング ツリー プリム アルゴリズムの Java コード テンプレート

public static int prim(int n, int[][] map) {//从下标1开始记录图的数据,n个节点,返回最小生成树的边权之和

		int[] dist = new int[n + 10];// 含义:这个点到最小生成树那个集合的最短距离,点到集合的距离
		boolean[] st = new boolean[n + 10];// st数组表示这个点有没有被加入最小生成树集合,如果被加入了,st[i]=true
		Arrays.fill(dist, INF);// 初始化距离

		int result = 0;// 记录最小生成树所有边权之和

		for (int i = 0; i < n; i++) {
			int t = -1;// 第一个点时情况特别判断
			for (int j = 1; j <= n; j++) {// 找到集合外距离集合最近的点
				if (st[j] == false && (t == -1 || dist[t] > dist[j]))
					t = j;
			}
			if (i != 0 && dist[t] == INF)// 如果最小的节点长度都为INF,那么不用找了,不存在最小生成树
				return INF;
			if (i != 0)// 如果这个点不是第一个点,将这个点距离加入
				result += dist[t];

			st[t] = true;// 将t这个点加入集合当中
			for (int j = 1; j <= n; j++)// 用这个点来更新其他点到这个集合的最短距离
				dist[j] = Math.min(dist[j], map[t][j]);// 这个时候t这个点已经被加入集合当中了,所以其他点到集合的距离可以用t来更新,因为t也在集合当中。

		}
		return result;
	}

最小スパニング ツリー (無向グラフ) の Kruskal アルゴリズム

最小スパニング ツリー クラスカル アルゴリズム Java コード テンプレート

static int[] p;

	public static int Find(int x) {// 并查集路径压缩优化
		if (p[x] != x)
			p[x] = Find(p[x]);
		return p[x];
	}
// kruskal算法略显繁琐,需要用到并查集
	public static int kruskal(int n, int[][] way) {// n个点,way记录的是边的信息
		
		p=new int[n+10];
		
		Arrays.sort(way, new Comparator<int[]>() {// 重写比较器,以边的权值作为比较依据
			public int compare(int[] o1, int[] o2) {
				return o1[2] - o2[2];
			}
		});

		for (int i = 1; i <= n; i++)// 并查集初始化每一个点,都是以自己为根节点的集合
			p[i] = i;

		int result = 0, count = 0;
		for (int i = 0; i < way.length; i++) {
			int a = way[i][0];
			int b = way[i][1];
			int c = way[i][2];
			a = Find(a);// 查询a的根节点
			b = Find(b);// 查询b的根节点
			if (a != b) {// 如果a和b不在一个集合里面
				p[a] = b;// 将a的根节点的父节点指向b
				result += c;// 加上这条边的距离
				count++;// 合并的点数加1
			}
		}

		if (count < n - 1)// 如果连通的点少于了点的总个数,说明不能构成最小生成树
			return Integer.MIN_VALUE;
		return result;

	}

単一ソース最短経路のダイクストラ アルゴリズム (無向グラフ)

単一ソースの最短パス ダイクストラ アルゴリズム Java コード テンプレート

public static int[] Dijkstra(int[][] map) {// 传入一个临界矩阵存放的图,从下标0开始为第一个点,返回所有点到第一个节点的最短距离数组。
		// 注意邻接矩阵存放的图初始化的数值是由你自己确认的!
		int n = map.length;
		int[] dist = new int[n];// 存放点到初始点的距离
		boolean[] st = new boolean[n];// 存放是否确定到初始点的距离最短
		Arrays.fill(dist, Integer.MAX_VALUE);// 初始化存放的所有节点到第一个节点的距离为无穷大

		dist[0] = 0;// 初始点到自己的距离为0

		for (int i = 0; i < n - 1; i++) {
			int temp = -1;
			for (int j = 0; j < n; j++) {// 如果矩阵从1开始存放节点信息,修改为for (int j = 1; j <= n; j++)

				if (st[j] == false && (temp == -1 || dist[temp] > dist[j]))// 第一次替换找到没有标记确定的第一个点,之后循环找距离初始点最近的没有标记确定的点
					temp = j;
			}

			// 如果矩阵从1开始存放节点信息,修改为for (int j = 1; j <= n; j++)
			for (int j = 0; j < n; j++) {// 通过上一步找到的点来更新这个点能够到达的其他点的距离
				// map[temp][j]表示temp到j这个点的距离,再加上dist[temp]就表示初始点以temp为中间点到j的距离
				dist[j] = Math.min(dist[j], dist[temp] + map[temp][j]);
			}
			st[temp] = true;// 更新完成之后,将该点标记为确定
		}
		return dist;// 返回结果
	}

単一ソース最短パスのベルマンフォード アルゴリズム (有向グラフ)

単一ソース最短パスのベルマンフォード アルゴリズム Java コード テンプレート

public static int[] Bellman_Ford(int n, int[][] way) {// n个点,way表示边的信息,way[i][j]=a表示从i到j距离为a,节点的下标从1开始记录,返回从第一个点到所有点最近的距离

		int[] dist = new int[510];// 存放到某点的距离
		int[] temp = new int[3];// 存放单条边
		Arrays.fill(dist, Integer.MAX_VALUE / 20);// 初始化
		dist[1] = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				temp = way[j];
				dist[temp[1]] = Math.min(dist[temp[1]], dist[temp[0]] + temp[2]);
			}
		}
		return dist;
	}

複数ソース最短経路のフロイド アルゴリズム (有向グラフ)

マルチソース最短パス用の Floyd アルゴリズム Java コード テンプレート

public static int[][] floyd(int n, int[][] map) {// 三重循环,n个点传入邻接矩阵存放的图map,返回多个点之间的最短路径数组
		// 刚开始传入的是邻接矩阵图,返回的是距离map[i][j]=a表示从i到j最短距离为a
		// 刚开始邻接矩阵的初始化自行处理。
		for (int k = 1; k <= n; k++) {
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++)
					map[i][j] = Math.min(map[i][j], map[i][k] + map[k][j]);
			}
		}
		return map;
	}

warshall アルゴリズムは、グラフが接続されているかどうかを決定します (隣接行列はグラフを保存します)。

public static boolean Warshall(int[][] tmp, int n) {// 传入这个图的邻接矩阵和节点个数。判断图是否连通,连通返回true

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (tmp[i][j] == 1) {
					for (int k = 0; k < n; k++) {
						if (tmp[k][i] == 1)
							tmp[k][j] = tmp[j][k] = 1;
					}
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				if (tmp[i][j] != 1)
					return false;
		return true;
	}

おすすめ

転載: blog.csdn.net/weixin_41746479/article/details/121291233