图的复习&&力扣题&&java的学习

克鲁斯卡尔算法简介

克鲁斯卡尔(Kruskal)算法是一种用来寻找最小生成树的算法(用来求加权连通图的最小生成树的算法)。在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。

板子:

#include<stdio.h>
  
#define MAXEDGE 100
#define MAXVERTEX 100
typedef struct Edge {
    int begin;//边的起点
    int end;  //边的终点
    int wight;//边的权值
} Edge;
  
typedef struct Graph {
    char vertex[MAXVERTEX];//顶点
    Edge edges[MAXEDGE];//边
    int numvertex,numedges;//顶点和边的个数
} MGraph;
  
void CreateGraph(MGraph* G) {
    printf("请输入顶点和边的个数:\n");
    scanf("%d%d", &G->numvertex, &G->numedges);
    printf("请输入顶点:\n");
    getchar();//利用该函数除去上一系我们在输入结束时按得回车符
    for (int i = 0; i < G->numvertex; i++) {
        scanf("%c", &G->vertex[i]);
    }
    printf("按权值从小到大输入边(vi,vj)对应的起点和终点的下标,begin,end以及权值wight:\n");
    for (int k = 0; k < G->numedges; k++) {
        Edge e;
        scanf("%d%d%d", &e.begin, &e.end, &e.wight);
        G->edges[k] = e;
    }
}
  
int Find(int *parent, int f) {
    while (parent[f]>0) {
        f = parent[f];
    }
    return f;
}
  
//最小生成树,克鲁斯卡尔算法
void Kruskal(MGraph *G) {
  
    int parent[MAXVERTEX];//存放最小生成树的顶点
    for (int i = 0; i < G->numvertex; i++) {
        parent[i] = 0;
    }
    int m, n;
    for (int i = 0; i < G->numedges; i++) {
        n = Find(parent, G->edges[i].begin);
        m = Find(parent, G->edges[i].end);
        if (n != m) { //m=n说明有环
            parent[n] = m;
            printf("(%d,%d) %d\t", G->edges[i].begin, G->edges[i].end, G->edges[i].wight);//打印边和权值
        }
    }
}
  
int main() {
    MGraph G;
    CreateGraph(&G);
    Kruskal(&G);
  
    return 0;
}

迪杰斯特拉算法
 

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
  
#define INFINITY 65535//无边时的权值
#define MAX_VERTEX_NUM 10//最大顶点数
  
typedef struct MGraph {
    string vexs[10];//顶点信息
    int arcs[10][10];//邻接矩阵
    int vexnum, arcnum;//顶点数和边数
} MGraph;
  
int LocateVex(MGraph G, string u) { //返回顶点u在图中的位置
    for(int i=0; i<G.vexnum; i++)
        if(G.vexs[i]==u)
            return i;
    return -1;
}
  
void CreateDN(MGraph &G) { //构造有向网
    string v1, v2;
    int w;
    int i, j, k;
    cout<<"请输入顶点数和边数:";
    cin>>G.vexnum>>G.arcnum;
  
    cout<<"请输入顶点:";
    for(i=0; i<G.vexnum; i++)
        cin>>G.vexs[i];
  
    for(i=0; i<G.vexnum; i++)
        for(j=0; j<G.vexnum; j++)
            G.arcs[i][j]=INFINITY;
  
    cout<<"请输入边和权值:"<<endl;
    for(k=0; k<G.arcnum; k++) {
        cin>>v1>>v2>>w;
        i=LocateVex(G, v1);
        j=LocateVex(G, v2);
        G.arcs[i][j]=w;
    }
}
  
//迪杰斯特拉算法求有向网G的v0顶点到其余顶点v的最短路径p[v]及带权长度D[v]
//p[][]=-1表示没有路径,p[v][i]存的是从v0到v当前求得的最短路径经过的第i+1个顶点(这是打印最短路径的关键),则v0到v的最短路径即为p[v][0]到p[v][j]直到p[v][j]=-1,路径打印完毕。
//final[v]为true当且仅当v∈S,即已经求得从v0到v的最短路径。
void ShortestPath_DIJ(MGraph G, int v0, int p[][MAX_VERTEX_NUM], int D[]) {
    int v, w, i, j, min;
    bool final[10];
  
    for(v=0; v<G.vexnum; v++) {
        final[v]=false;//设初值
        D[v]=G.arcs[v0][v];//D[]存放v0到v得最短距离,初值为v0到v的直接距离
        for(w=0; w<G.vexnum; w++)
            p[v][w]=-1;//设p[][]初值为-1,即没有路径
        if(D[v]<INFINITY) { //v0到v有直接路径
            p[v][0]=v0;//v0到v最短路径经过的第一个顶点
            p[v][1]=v;//v0到v最短路径经过的第二个顶点
        }
    }
  
    D[v0]=0;//v0到v0距离为0
    final[v0]=true;//v0顶点并入S集
  
    for(i=1; i<G.vexnum; i++) { //其余G.vexnum-1个顶点
        //开始主循环,每次求得v0到某个顶点v的最短路径,并将v并入S集,然后更新p和D
        min=INFINITY;
        for(w=0; w<G.vexnum; w++)//对所有顶点检查
            if(!final[w] && D[w]<min) { //在S集之外(即final[]=false)的顶点中找离v0最近的顶点,将其赋给v,距离赋给min
                v=w;
                min=D[w];
            }
        final[v]=true;//v并入S集
        for(w=0; w<G.vexnum; w++) { //根据新并入的顶点,更新不在S集的顶点到v0的距离和路径数组
            if(!final[w] && min<INFINITY && G.arcs[v][w]<INFINITY && (min+G.arcs[v][w]<D[w])) {
                //w不属于S集且v0->v->w的距离<目前v0->w的距离
                D[w]=min+G.arcs[v][w];//更新D[w]
                for(j=0; j<G.vexnum; j++) { //修改p[w],v0到w经过的顶点包括v0到v经过的所有顶点再加上顶点w
                    p[w][j]=p[v][j];
                    if(p[w][j]==-1) { //在p[w][]第一个等于-1的地方加上顶点w
                        p[w][j]=w;
                        break;
                    }
                }
  
            }
        }
    }
}
  
int main() {
    int i, j;
    MGraph g;
    CreateDN(g);
    int p[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//最短路径数组p
    int D[MAX_VERTEX_NUM];//最短距离数组D
    ShortestPath_DIJ(g, 0, p, D);
  
    cout<<"最短路径数组p[i][j]如下:"<<endl;
    for(i=0; i<g.vexnum; i++) {
        for(j=0; j<g.vexnum; j++)
            cout<<setw(3)<<p[i][j]<<" ";
        cout<<endl;
    }
  
    cout<<g.vexs[0]<<"到各顶点的最短路径及长度为:"<<endl;
    for(i=0; i<g.vexnum; i++) {
        if(i!=0 && D[i]!=INFINITY) {
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<"的最短路径长度为:"<<D[i];
            cout<<"  最短路径为:";
            for(j=0; j<g.vexnum; j++) {
                if(p[i][j]>-1)
                    cout<<g.vexs[p[i][j]]<<" ";
            }
            cout<<endl;
        } else if(D[i]==INFINITY)
            cout<<g.vexs[0]<<"-"<<g.vexs[i]<<":"<<"不可达"<<endl;
    }
    return 0;
}

“割”思想

我们通过切一刀,能够把有序数组分成左右两个部分,切的那一刀就被称为割,割的左右会有两个元素,分别是左边最大值和右边最小值。

 


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

#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))

class Solution {
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
		int n = nums1.size();
		int m = nums2.size();

		if (n > m)  //保证数组1一定最短
		{
			return findMedianSortedArrays(nums2, nums1);
		}

		// Ci 为第i个数组的割,比如C1为2时表示第1个数组只有2个元素。LMaxi为第i个数组割后的左元素。RMini为第i个数组割后的右元素。
		int LMax1, LMax2, RMin1, RMin2, c1, c2, lo = 0, hi = 2 * n;  //我们目前是虚拟加了'#'所以数组1是2*n长度

		while (lo <= hi)   //二分
		{
			c1 = (lo + hi) / 2;  //c1是二分的结果
			c2 = m + n - c1;

			LMax1 = (c1 == 0) ? INT_MIN : nums1[(c1 - 1) / 2];
			RMin1 = (c1 == 2 * n) ? INT_MAX : nums1[c1 / 2];
			LMax2 = (c2 == 0) ? INT_MIN : nums2[(c2 - 1) / 2];
			RMin2 = (c2 == 2 * m) ? INT_MAX : nums2[c2 / 2];

			if (LMax1 > RMin2)
				hi = c1 - 1;
			else if (LMax2 > RMin1)
				lo = c1 + 1;
			else
				break;
		}
		return (max(LMax1, LMax2) + min(RMin1, RMin2)) / 2.0;
	}
};


int main(int argc, char *argv[])
{
	vector<int> nums1 = { 2,3, 5 };
	vector<int> nums2 = { 1,4,7, 9 };
	
	Solution solution;
	double ret = solution.findMedianSortedArrays(nums1, nums2);
	return 0;
}

 java学习

 

public class Main {
    public static void main(String[] args) {
        int a = 5;
        int b = 10;
        System.out.println("a == b = " + (a == b) );
        System.out.println("a != b = " + (a != b) );
        System.out.println("a > b = " + (a > b) );
        System.out.println("a < b = " + (a < b) );
        System.out.println("a >= b = " + (a >= b) );
        System.out.println("a <= b = " + (a <= b) );
    }
}

 

 

public class Main {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        System.out.println("a && b = " + (a&&b));
        System.out.println("a || b = " + (a||b) );
        System.out.println("!(a && b) = " + !(a && b));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏生十一_Nojambot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值