그림 의 인접 행렬 (저장 구조, 그림 의 옮 겨 다 니 기, 최소 생 성 트 리, 관건 적 인 경로, 최 단 경로)

그림 의 분류 와 구조
그림 은 유방 향도 (DG), 유방 향망 (DN), 무방 향도 (UDG), 무방 향망 (UDN) 으로 나 눌 수 있다
인접 행렬 의 저장 구조
//    
typedef struct{
     
	ElemType vexs[N]; //          
	int arcs[N][N]; //            
	//        arcs[i][j] =         ( i = j     0) 
	int vexnum, arcnum; //         
}MGraph;

인접 행렬 의 방식 구조 도 (무방 향 도 예)
//         
int LocateVex(MGraph G, ElemType v)
{
     //         
	int i;
	for(i = 0; i<G.vexnum; i++)
	{
     
		if(v == G.vexs[i])
			return i;		
	}
	return -1; //         -1 
}
void Create_UDN(MGraph &G)
{
     
	int i, j;
	ElemType v1, v2;
	int a1, a2;
	scanf("%d %d", &G.vexnum, &G.arcnum);//        
	//      
	for(i = 0;i<G.vexnum; i++) //     
		scanf("%d", &G.vexs[i]);
	//       
	for(i = 0; i<G.vexnum; i++)
	{
     
		for(j = 0; j<G.vexnum; j++)
		{
     
			G.arcs[i][j] = 0; //              
		}
	}
	//       
	for(i = 0; i<G.arcnum; i++)
	{
     
		scanf("%d %d", &v1, &v2);
		a1 = LocateVex(G, v1);
		a2 = LocateVex(G, v2);
		G.arcs[a1][a2] = G.arcs[a2][a1] = 1;
		//         G.arcs[a1][a2] = 1
	}
}

그림 의 편력
1. 깊이 우선 옮 겨 다 니 기 (Depth First Search)
알고리즘 사상: 1. 그림 의 한 정점 v 에서 출발 하여 이 정점 을 방문 한 다음 에 v 의 방문 되 지 않 은 인접 정점 에서 깊이 있 게 그림 을 옮 겨 다 니 며 그림 의 모든 v 와 연 결 된 정점 이 방문 되 었 을 때 까지.2. 만약 에 이 그림 에 정점 이 방문 되 지 않 았 다 면 (즉, 연결 되 지 않 은 그림) 방문 되 지 않 은 정점 의 시작 점 을 선택 하고 이 과정 을 반복 하여 모든 정점 이 방문 되 었 을 때 까지 합 니 다.
  • 방법 1:
  • int visited[N]; //  0      
    int FirstAdjVex(MGraph G, int v)
    {
         // v          ,      -1
    	int i, j;
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		if(G.arcs[v][i] == 1)
    			return i;
    	}
    	return -1;
    }
    int NextAdjVex(MGraph G ,int v, int w)
    {
         // v          
    	int i;
    	for(i = w+1; i<G.vexnum; i++)
    	{
         
    		if(G.arcs[v][i] == 1)
    			return i;
    	}
    	return -1;
    }
    //      v(    )         
    void DFS(MGraph G, int v)
    {
         
    	//  v,   
    	printf("%d ", G.vexs[v]);
    	visited[v] = 1;
    	int w;
    	//v          
    	w = FirstAdjVex(G, v);
    	while(w>=0)
    	{
         
    		if(visited[w] == 0)  //  w       w 
    			DFS(G, w);
    		w = NextAdjVex(G ,v, w); //   v      
    	}
    }
    
    void DFSTraverse(MGraph G)
    {
         
    	int i;
    	for(i = 0; i<G.vexnum; i++)
    		visited[i] = 0; //         
    	for(i = 0; i<G.vexnum; i++)
    		if(visited[i] == 0) //   i       ,   DFS 
    			DFS(G, i);
    }
    
  • 방법 2
  • void DFS(MGraph G, int v)
    {
         
    	int i;
    	printf("%d,",G.vexs[v]);
    	visited[v] = 1;
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		if(visited[i]==0 && G.arcs[v][i] == 1)
    		{
         
    			DFS(G, i);
    		}
    	}
    }
    
    void DFSTraverse(MGraph G)
    {
         
    	int i;
    	for(i = 0; i<G.vexnum; i++)
    		visited[i] = 0; //         
    	for(i = 0; i<G.vexnum; i++)
    		if(visited[i] == 0) //   i       ,   DFS 
    			DFS(G, i);
    }
    

    2. 범위 우선 옮 겨 다 니 기 (Broadth First Search)
  • 방법 1
  • //           (Broadth_First Search) 
    void BFSTraverse(MGraph G)
    {
         
    	//  
    	int Q[N]; //    
    	int front, rear; //          
    	front = rear = 0;
    	int i, j;
    	int v;
    	for(i = 0; i<G.arcnum; i++)
    		visited[i] = 0;
    	
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		if(visited[i] == 0)
    		{
         
    			//      
    			Q[rear++] = i;
    			visited[i] = 1;
    			printf("%d ", G.vexs[i]); 
    			//*************************************   
    			while(front != rear)
    			{
         
    				//  
    				v = Q[front++];
    				// v       
    				for(j = 0; j<G.vexnum; j++)
    					
    					if(G.arcs[v][j] == 1 && visited[j]==0)
    					{
         
    						Q[rear++] = j;
    						visited[j] = 1;
    						printf("%d ", G.vexs[j]);
    					}		
    			}
    		}
    	}
    }
    
  • 방법 2
  • //           (Broadth_First Search) 
    void BFSTraverse(MGraph G)
    {
         
    	//  
    	int Q[N]; //    
    	int front, rear; //          
    	front = rear = 0;
    	int i, j;
    	int v;
    	for(i = 0; i<G.arcnum; i++)
    		visited[i] = 0;
    	
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		if(visited[i] == 0)
    		{
         
    			//      
    			Q[rear++] = i;
    			visited[i] = 1;
    			printf("%d ", G.vexs[i]); 
    			//*************************************    
    			
    			int v ,w;
    			while(front != rear)
    			{
         
    				//  
    				v = Q[front++];
    				w = FirstAdjVex(G, v);
    				while(w>=0)
    				{
         
    					if(!visited[w])
    					{
         //      
    						Q[rear++] = w;
    						visited[w] = 1;
    						printf("%d ", G.vexs[w]);
    					}
    					w = NextAdjVex(G , v, w);
    				}		
    			}
    		}
    	}
    }
    

    그림 의 흔 한 알고리즘
    최소 생 성 트 리
  • 구조 연결 망 의 생 성 나 무 는 전체적인 대 가 를 가장 적 게 한다. 최소 생 성 나무의 문제 이다.

  • 1. 프 림 알고리즘 (Prim)
    알고리즘 사상:
  • 보조 구조 배열 closege [n] 를 정의 하고 U 에서 V - U 까지 최소 대 가 를 가 진 변 을 기록 합 니 다.생 성 트 리 의 정점 vi * 8712 ° V - U 에 아직 가입 하지 않 았 습 니 다. 계산:
    closege[i-1].lowcost = Min{ cost(vi , u) | u∈U  }
    closege[i-1].vexs =  { u |   cost(vi  , u )     }
    
  • closege [k]. lowcost 의 가장 작은 정점 vk + 1 을 구하 고 U 에 가입 하 는 동시에 변 (vk + 1, closege [k]. vexs) 을 생 성 트 리 에 추가 합 니 다.
  • 1, 2 과정 을 반복 한다.U = V 까지.
  • //     (Prim) 
    void MiniTree_Prim(MGraph G, ElemType v)
    {
         //  v     
    	struct{
         
    		int lowcost; //   0         
    		ElemType vex; //closege[i].vex, i             
    	}closege[N];
    	
    	int i, j, k;
    	int w; //        
    	w = LocateVex(G, v);
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		//   closege[]  
    		if(i != w)
    			closege[i].lowcost = G.arcs[w][i];
    		else
    			closege[i].lowcost = 0;
    		closege[i].vex = v;
    	}
    	int t;
    	for(i = 1; i<G.vexnum; i++)//     G.vexnum-1   
    	{
         
    		int min = 99999;
    		//     ,  U  
    		for(j = 0; j<G.vexnum; j++)
    		{
         
    			if(closege[j].lowcost < min && closege[j].lowcost != 0)
    			{
         
    				min = closege[j].lowcost;
    				t = j;
    			}
    		}
    		printf("%d %d,", closege[t].vex, G.vexs[t]);
    		closege[t].lowcost = 0; //    U ,         
    		//   
    		for(k = 0; k<G.vexnum; k++)
    		{
         
    			if(G.arcs[t][k] < closege[k].lowcost)
    			{
         
    				closege[k].lowcost = G.arcs[t][k];
    				closege[k].vex = G.vexs[t];
    			}	
    		}
    	}
    }
    

    2. 크 루스 칼 알고리즘 (Kruskal)
    알고리즘 사상:
  • 설정 T = (V, {E}) 은 하나의 연결 그림 으로 최소 생 성 트 리 의 초기 상 태 를 n 개의 정점 만 있 고 끝 이 없 는 비 연결 그림 으로 합 니 다. 즉, T = (V, {}) 그림 의 정점 마다 하나의 연결 분량 을 만 듭 니 다.
  • E 에서 대가 가 가장 적은 쪽 을 선택한다.제약 조건: 이 변 에 붙 어 있 는 정점 이 T 의 서로 다른 연결 분량 에 떨 어 지면 이 변 을 T 에 넣 습 니 다.그렇지 않 으 면 이 쪽 을 버 리 고 다음 대가 가 가장 적은 쪽 을 선택한다.
  • T 의 모든 정점 이 같은 연결 분량 에 있 을 때 까지 순서대로 유추 했다.

  • AOV - 네트 랑 AOE. - 네트.
  • AOE - 망: 활동 의 방향 유 무 환 도 를 나타 낸다.정점 은 사건 을 나타 내 고 호 는 활동 을 나타 내 며 가중치 는 활동 이 지속 되 는 시간 을 나타 낸다.보통 AOE - 망 은 공사 완료 시간 을 추산 하 는 데 사용 된다.(토폴로지 정렬)
  • AOV - 네트워크: 정점 으로 활동 을 표시 하고 호 로 활동 간 의 우선 관 계 를 나타 내 는 방향 도 를 정점 으로 활동 을 나타 내 는 네트워크 라 고 한다.(관건 적 인 경로)
  • 토폴로지 정렬 (Topological Sort), AOV - 네트워크
    알고리즘 사상:
  • 그림 에서 전구 가 없 는 정점 을 선택 하고 출력 합 니 다.
  • 그림 에서 이 정점 과 이 를 끝 으로 하 는 모든 호 를 삭제 합 니 다.
  • 1.2 과정 을 반복 하여 모든 정점 이 출력 되 었 거나 현재 그림 에 전구 가 없 는 정점 이 없 을 때 까지 이 상황 은 그림 에 고리 가 있 음 을 나타 낸다.
  • //    (Topological Sort),             
    void TopologicalSort(MGraph G)
    {
         
    	//      
    	int degree[N] = {
         0};
    	int S[N]; //               
    	int top = 0; //    
    	int t; //t        
    	int i, j;
    	int n = 0; //         ,           
    	for(i = 0; i<G.vexnum;i++)
    		for(j = 0; j<G.vexnum;j++)
    			degree[i]+=G.arcs[j][i];
    	//          
    	for(i = 0; i<G.vexnum; i++)
    		if(degree[i] == 0)
    			S[top++] = i;
    	while(top != 0)
    	{
         
    		//          
    		t = S[--top];
    		printf("%d ", G.vexs[t]);
    		n++; 
    		//    -1,     0      
    		for(i = 0; i<G.vexnum; i++)
    		{
         
    			if(G.arcs[t][i] == 1)
    			{
         
    				degree[i]--;
    				if(degree[i] == 0)
    					S[top++] = i;
    			}
    		}
    	}
    	if(n<G.vexnum)
    		printf("       "); 
    }
    

    관건 적 인 경로 문제, AOE - 네트워크
  • 시작 점 에서 완성 점 까지 의 가장 긴 경로 의 길이. 즉, 경로 상 각 활동 지속 시간의 합
  • 알고리즘 사상:
  • e 개의 호 를 입력 하고 AOE - 네트워크 의 저장 구 조 를 구축한다.
  • 원점 V0 에서 출발 하여 ve [0] = 0;토폴로지 에 따라 나머지 각 정점 의 ve [i] 를 질서 있 게 구하 기;만약 에 얻 은 서열 에서 정점 의 개수 가 네트워크 의 정점 총수 보다 적 으 면 관건 적 인 경 로 를 구 할 수 없고 알고리즘 이 종 료 됩 니 다.그렇지 않 으 면 실행 절차 (3);
  • 외환 점 Vn 에서 출발 하여 vl [n - 1] = ve [n - 1] 를 역 토폴로지 에 따라 나머지 각 정점 의 vl [i] 를 질서 있 게 구한다.
  • 각 정점 의 ve 와 vL 에 따라 각 호 s 의 e [s] 와 L [s] 를 구하 고 e [s] = L [s] 를 만족 시 키 면 관건 적 인 활동 이다.
  • //      
    int ve[N] = {
         0}; //  ai        
    int vl[N] = {
         0}; //  ai        
    int T[N];
    int top1 = -1; //             
    int S[N];
    int top2 = -1; //               
    Status TopologicalOrder(MGraph G)
    {
         
    	int i, j;
    	int degree[N] = {
         0}; //      
    
    	int e; //         
    	int count; //           ,               ,     
    	//     
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		for(j = 0; j<G.vexnum; j++)
    		{
         
    			if(G.arcs[i][j] > 0 && G.arcs[i][j] < MAX)
    				degree[j]++;
    		}
    	}
    
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		if(degree[i] == 0)
    		{
         
    			S[++top2] = i; //      
    			T[++top1] = i; //      
    			count++;
    		}
    			
    	}
    	//    ,              
    	while(top2 != -1)
    	{
         
    		e = S[top2--]; 
    		for(i = 0; i<G.vexnum; i++)
    		{
         
    			if(G.arcs[e][i] < MAX && G.arcs[e][i] != 0)
    			{
         
    				degree[i]--;
    				if(degree[i] == 0)
    				{
         
    					S[++top2] = i;
    					T[++top1] = i;
    					count++;
    					if(ve[e] + G.arcs[e][i] > ve[i])
    						ve[i] = ve[e] + G.arcs[e][i];
    				}	
    			}
    		}
    	}
    	if(count < G.vexnum)
    	{
         
    		return 0;
    	}
    	return 1;
    }
    //              
    Status CtriticalPath(MGraph G)
    {
         
    	if(!TopologicalOrder(G))
    		return 0;
    	int i;
    	int e;
    	e = T[top1--];
    	//            
    	for(i = 0; i<G.vexnum; i++)
    		vl[i] = ve[e];
    	//   , T     ,              
    	while(top1 != -1)
    	{
         	
    		for(i = 0; i<G.vexnum; i++)
    		{
         
    			if(G.arcs[i][e] > 0 && G.arcs[i][e] < MAX)
    			{
         
    				if(vl[e]-G.arcs[i][e] < vl[i])
    					vl[i] = vl[e]-G.arcs[i][e];
    			}
    		}
    		e = T[top1--];
    	}
    	//      
    	for(i = 0; i<G.vexnum; i++)
    		if(ve[i] == vl[i])
    			printf("%d %d,", i,ve[i]);	
    	return 1;
    }
    

    질문
    1. 디 제 스 트 라 알고리즘 (Dijkstra)
  • 목적: 원점 에서 나머지 각 정점 까지 의 최 단 경로
  • 알고리즘 사상:
  • 1. 정의 D [i]: 현재 찾 은 원점 V0 에서 Vi 까지 의 가장 짧 은 경 로 를 나타 낸다.초기 상태: D [i] = G. arcs [v0] [vi] 즉 호의 가중치.
  • D[j] = Min( D[i] ) (i=1,…., n-1)。분명히 Vj 는 V0 에서 출발 하여 가장 먼저 도착 한 길이 가 가장 짧 은 정점 이다.
  • 다음 최 단 경 로 는 D [k] = min (D [k], D [j] + G. arcs [j] [k]) 입 니 다.
  • 같은 이치 로 다음 의 모든 최 단 경 로 를 구한다.
  • void ShortestPath_DIJ(MGraph &G, int v0)
    {
         
    	int D[N]; //D[v]     V0 V           
    	int P[N]; //     V0 V                 W。
    	int final[N]; //    V          。0     ,1      
    	int i, j ,v;
    	
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		D[i] = G.arcs[v0][i];
    		P[i] = v0;
    		final[i] = 0;
    	}
    	final[v0] = 1;
    	D[v0] = 0;
    	
    	for(i = 1; i<G.vexnum; i++)
    	{
         
    		int min = 999999;
    		int v;
    		for(j = 0; j<G.vexnum; j++)
    		{
         
    			if(D[j] < min && final[j] == 0)
    			{
         
    				min = D[j];
    				v = j;
    			}
    		}
    		final[v] = 1;
    		for(j = 0; j<G.vexnum; j++) //         
    		{
         
    			if(D[j] > G.arcs[v0][v] + G.arcs[v][j])
    			{
         
    				D[j] = G.arcs[v0][v] + G.arcs[v][j];
    				P[j] = v;
    			}
    		}
    	}
    }
    

    1. 프로 이 드 알고리즘 (Floyd)
  • 목적: 한 쌍 의 정점 간 의 최 단 경로
  • //      (Floyd) 
    void ShortestPath_FLOYD(MGraph G)
    {
         
    	int i, j, k;
    	int D[N][N]; //D[i][j]   i     j           
    	int P[N][N]; //P[i][j]   i     j                 
    	//    
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		for(j = 0; j<G.vexnum; j++)
    		{
         
    			D[i][j] = G.arcs[i][j];
    			P[i][j] = i;
    		} 
    	}
    	
    	for(i = 0; i<G.vexnum; i++)
    	{
         
    		for(j = 0; j<G.vexnum; j++)
    		{
         
    			for(k = 0; k<G.vexnum; k++)
    			{
         
    				if(D[j][k] > D[j][i] + D[i][k])
    				{
         
    					D[j][k] = D[j][i] + D[i][k];
    					P[j][k] = i;
    				}
    			}
    		}
    	}
    }**
    

    좋은 웹페이지 즐겨찾기