In computer science, Kosaraju-Sharir's algorithm (also known as Kosaraju's algorithm) is a linear time algorithm to find the strongly connected components of a directed graph.  Aho, Hopcroft and Ullman credit it to S. Rao Kosaraju and Micha Sharir. Kosaraju suggested it in 1978 but did not publish it, while Sharir independently discovered it and published it in 1981. It makes use of the fact that the transpose graph (the same graph with the direction of every edge reversed) has exactly the same strongly connected components as the original graph.

The algorithm
The primitive graph operations that the algorithm uses are to enumerate the vertices of the graph, to store data per vertex (if not in the graph data structure itself, then in some table that can use vertices as indices), to enumerate the out-neighbours of a vertex (traverse edges in the forward direction), and to enumerate the in-neighbours of a vertex (traverse edges in the backward direction); however the last can be done without, at the price of constructing a representation of the transpose graph during the forward traversal phase. The only additional data structure needed by the algorithm is an ordered list  of graph vertices, that will grow to contain each vertex once.

If strong components are to be represented by appointing a separate root vertex for each component, and assigning to each vertex the root vertex of its component, then Kosaraju's algorithm can be stated as follows.
 For each vertex  of the graph, mark  as unvisited. Let  be empty.
 For each vertex  of the graph do , where  is the recursive subroutine:
 If  is unvisited then:
 Mark  as visited.
 For each out-neighbour  of , do .
 Prepend  to .
 Otherwise do nothing.
 For each element  of  in order, do  where  is the recursive subroutine:
 If  has not been assigned to a component then:
 Assign  as belonging to the component whose root is .
 For each in-neighbour  of , do .
 Otherwise do nothing.
Trivial variations are to instead assign a component number to each vertex, or to construct per-component lists of the vertices that belong to it. The unvisited/visited indication may share storage location with the final assignment of root for a vertex.

The key point of the algorithm is that during the first (forward) traversal of the graph edges, vertices are prepended to the list  in post-order relative to the search tree being explored. This means it does not matter whether a vertex  was first visited because it appeared in the enumeration of all vertices or because it was the out-neighbour of another vertex  that got visited; either way  will be prepended to  before  is, so if there is a forward path from  to  then  will appear before  on the final list  (unless  and  both belong to the same strong component, in which case their relative order in  is arbitrary). 

This means, that each element  of the list can be made to correspond to a block , where the block consists of all the vertices reachable from vertex  using just outward edges at each node in the path. It is important to note that no vertex in the block beginning at  has an inward link from any of the blocks beginning at some vertex to its right, i.e., the blocks corresponding to vertices  in the list. This is so, because otherwise the vertex having the inward link(say from the block beginning at )would have been already visited and pre-pended to  in the block of , which is a contradiction. On the other hand, vertices in the block starting at  can have edges pointing to the blocks starting at some vertex in 

Step 3 of the algorithm, starts from , assigns all vertices which point to it, the same component as . Note that these vertices can only lie in the block beginning at  as higher blocks can't have links pointing to vertices in the block of . Let the set of all vertices that point to  be . Subsequently, all the vertices pointing to these vertices,  are added too, and so on till no more vertices can be added. 

There is a path to , from all the vertices added to the component containing . And there is a path to all the vertices added from , as all those lie in the block beginning at (which contains all the vertices reachable from  following outward edges at each step of path). Hence all these form a single strongly connected component. Moreover, no vertex remains, because, to be in this strongly connected component a vertex must be reachable from  and must be able to reach . All vertices that are able to reach , if any, lie in the first block only, and all the vertices in first block are reachable from . So the algorithm chooses all the vertices in the connected component of . 

When we reach vertex , in the loop of step 3, and  hasn't been assigned to any component, we can be sure that all the vertices to the left have made their connected components; that  doesn't belong to any of those components; that  doesn't point to any of the vertices to the left of it. Also, since, no edge from higher blocks to 's block exists, the proof remains same. 

As given above, the algorithm for simplicity employs depth-first search, but it could just as well use breadth-first search as long as the post-order property is preserved.

The algorithm can be understood as identifying the strong component of a vertex  as the set of vertices which are reachable from  both by backwards and forwards traversal. Writing  for the set of vertices reachable from  by forward traversal,  for the set of vertices reachable from  by backwards traversal, and  for the set of vertices which appear strictly before  on the list  after phase 2 of the algorithm, the strong component containing a vertex  appointed as root is
 
Set intersection is computationally costly, but it is logically equivalent to a double set difference, and since  it becomes sufficient to test whether a newly encountered element of  has already been assigned to a component or not.

Complexity 
Provided the graph is described using an adjacency list, Kosaraju's algorithm performs two complete traversals of the graph and so runs in Θ(V+E) (linear) time, which is asymptotically optimal because there is a matching lower bound (any algorithm must examine all vertices and edges). It is the conceptually simplest efficient algorithm, but is not as efficient in practice as Tarjan's strongly connected components algorithm and the path-based strong component algorithm, which perform only one traversal of the graph.

If the graph is represented as an adjacency matrix, the algorithm requires Ο(V2) time.

References 
 Alfred V. Aho, John E. Hopcroft, Jeffrey D. Ullman. Data Structures and Algorithms. Addison-Wesley, 1983.
 Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. Introduction to Algorithms, 3rd edition. The MIT Press, 2009. .
 Micha Sharir. A strong-connectivity algorithm and its applications to data flow analysis.  Computers and Mathematics with Applications 7(1):67–72, 1981.

External links 
Good Math, Bad Math: Computing Strongly Connected Components

Graph algorithms
Graph connectivity
컴퓨터 과학에서 코사라주 알고리즘 (코사라주-샤리르 알고리즘으로도 알려져 있다.)은 유향그래프에서의 강한 연결 요소를 선형 시간에 찾는 알고리즘이다. 앨프리드 에이호, 존 홉크로프트 및 제프리 울만은 이 알고리즘을 삼바시바 코사라주 및 미샤 샤리르의 것으로 보증한다. 삼바시바 코사라주는 1978년에 이 알고리즘을 제안하였지만 출판하지 않았고, 1981년 미샤 샤리르는 독자적으로 알고리즘을 발견하고 출판하였다. 이 알고리즘은 역방향 그래프(모든 간선들의 방향을 뒤집은 그래프)가 원래 그래프와 정확히 같은 강한 연결 요소를 갖는다는 사실을 이용한다.

알고리즘 
코사라주 알고리즘은 크게 네 가지의 그래프 연산을 바탕으로 한다.

 그래프의 정점들을 열거하는 연산
 정점마다 데이터를 저장하는 연산(그래프의 자료 구조 안에 저장하는 방법 뿐만 아니라 정점들을 인덱스로 하는 배열에 저장하는 방법도 있다.)
 정점에서 나가는 방향의 이웃(순방향 이웃) 정점들을 열거하는 연산(순방향 탐색)
 정점에서 들어오는 방향의 이웃(역방향 이웃) 정점들을 열거하는 연산(역방향 탐색) 

마지막 연산에서 원본 그래프를 역방향 그래프로 표현하는 것은 순방향 순회를 할 때 비용 없이 가능하다. 이 알고리즘에 필요한 유일한 자료 구조는 그래프 정점들의 순서가 매겨진 목록 L 이다. 이 목록은 각 정점을 한번씩 포함하게 된다.

만약 그래프의 강한 연결 요소들을 각 구성 요소에 대해 별도의 루트 정점을 지정하고 각 정점에 구성 요소의 루트 정점을 할당함으로써 표현할 경우 코사라주의 알고리즘은 다음과 같이 적용될 수 있다.

 그래프의 각 정점 u 에 대하여, u 를 방문되지 않은 것으로 표시한다. 이때, 목록 L 은 비어 있다.
 그래프의 각 정점 u 에 대하여 정점을 방문하는 함수인 Visit(u)를 수행하고, Visit(u)는 재귀적으로 서브루틴을 작동시킨다.
 만약 u 가 방문되지 않았다면:
 u 를 방문한 것으로 표시한다.
 u 의 바깥쪽 이웃 v 에 대해 Visit(v)를 수행한다.
 L 앞에 u 를 추가한다.
 그렇지 않으면:
      아무것도 하지 않는다
 L 에 순서에 따라 각 원소 u에 대하여 강한 연결 요소에 할당시키는 함수인 Assign(u,u) Assign(u,루트)는 재귀적으로 서브루틴을 작동시킨다.
 만약 u 가 할당되지 않은 요소라면:
 루트가 루트인 강한 연결 요소에 u를 포함시킨다.
 u 의 안쪽 이웃 v 에 대해 Assign(v,루트)를 수행한다.
 그렇지 않으면:
      아무것도 하지 않는다

각 정점에 강한 연결 요소의 번호를 할당하거나 강한 연결 요소 별로 포함하고 있는 정점의 리스트를 만드는 등의 사소한 변형이 가능하다. 방문하지 않음/방문함 표시의 저장 장소는 정점마다 루트를 최종적으로 할당할 때 공유될 수 있다.

이 알고리즘의 중요한 부분은 그래프 간선의 첫번째(순방향) 순회 때, 정점들이 트리가 탐색되는 순서와 같이 후위 순서의 관계로 검색트리 목록 L 에 추가된다는 것이다. 이것은 정점 v 가 처음 방문되었는지와 무관하다. 왜냐하면 정점 v 가 방문되는 경우는 모든 정점들이 나열된 L에서 나타나거나, 방문된 다른 정점 u가 v의 바깥 이웃이여서 나타나기 때문이다. L 에 v 가 u 보다 앞에 추가되었다는 것은 어느쪽으로든 간에 u에서 v로의 순방향 경로가 존재한다면 최종 리스트 L 에는 u 가 v 보다 앞에 나타나기 때문이다.(만약 u 와 v 모두 같은 강한 연결 요소에 포함되지 않는다면, L에서 그들의 상대적 순서는 임의적이다. 간결함을 위해 깊이 우선 탐색을 채용한 알고리즘이 위에 기술되어있지만, 후위 순회의 특성이 보존되는 경우 너비 우선 탐색에 대해서도 작동한다.

시간 복잡도 
그래프가 인접 리스트의 형태로 주어질 때, 코사라주의 알고리즘은 두 번의 그래프 순회가 수행되므로 최적의 경우  (선형)시간에 수행된다. 왜냐하면 어떠한 알고리즘이라도 반드시 모든 정점과 간선을 시험해봐야 하기 때문이다. 이것은 개념적으로 가장 간단한 효율적인 알고리즘이지만 오직 한번의 순회만 시행하는 타잔의 강한 연결 요소 알고리즘이나 경로 기반 강한 요소 알고리즘에 비해 비효율적이다.

그래프가 인접 행렬로 주어질 때 ,이 알고리즘은  시간에 작동된다.

각주 

 Alfred V. Aho, John E. Hopcroft, Jeffrey D. Ullman. Data Structures and Algorithms. Addison-Wesley, 1983.
 Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein. Introduction to Algorithms, 3rd edition. The MIT Press, 2009. .
 Micha Sharir. A strong-connectivity algorithm and its applications to data flow analysis.  Computers and Mathematics with Applications 7(1):67–72, 1981.
그래프 알고리즘