Open In App

Reverse Cuthill Mckee Algorithm

Improve
Improve
Like Article
Like
Save
Share
Report

The Cuthill-Mckee algorithm is used for reordering of a symmetric square matrix. It is based on Breadth First Search algorithm of a graph, whose adjacency matrix is the sparsified version of the input square matrix.
The ordering is frequently used when a matrix is to be generated whose rows and columns are numbered according to the numbering of the nodes. By an appropriate renumbering of the nodes, it is often possible to produce a matrix with a much smaller bandwidth

Sparsified version of a matrix is a matrix in which most of the elements are zero.
The Reverse Cuthill-Mckee Algorithm is the same as the Cuthill-Mckee algorithm, the only difference is that the final indices obtained using the Cuthill-Mckee algorithm are reversed in the Reverse Cuthill-Mckee Algorithm.

Below are the steps of Reverse Cuthill-Mckee algorithm: 

  1. Instantiate an empty queue Q and empty array for permutation order of the objects R.
  2. S1: We first find the object with minimum degree whose index has not yet been added to R. Say, object corresponding to pth row has been identified as the object with a minimum degree. Add p to R.
  3. S2: As an index is added to R, and add all neighbors of the corresponding object at the index, 
    in increasing order of degree, to Q. The neighbors are nodes with non-zero value amongst the non-diagonal elements in the pth row.
  4. S3: Extract the first node in Q, say C. If C has not been inserted in R, add it to R, add to Q the neighbors of C in increasing order of degree.
  5. S4: If Q is not empty, repeat S3.
  6. S5: If Q is empty, but there are objects in the matrix which have not been included in R, start from S1, once again. (This could happen if there are disjoint graphs)
  7. S6: Terminate this algorithm once all objects are included in R.
  8. S7: Finally, reverse the indices in R, i.e. (swap(R[i], R[P-i+1])).

Degree: Definition of a degree is not constant, it changes according to the dataset you are working with. For the example given below, the degree of a node is defined as the sum of non-diagonal elements in the corresponding row.

Generalized definition of the degree of a node ‘A’ is the number of nodes connected to ‘A’. 

Example: 

Given a symmetric matrix:  
| 0.0 0.78 0.79 0.8 0.23 |
| 0.9 0.0 0.43 0.771 0.752 |
| 0.82 0.0 0.0 0.79 0.34 |
| 0.8 0.8 0.8 0.0 0.8 |
| 0.54 0.97 0.12 0.78 0.0 |
Degree here is defined as sum of non-diagonal
elements in the corresponding row.
Specification for a matrix is defined as,
if the element of the matrix at i, j has a value
less than 0.75 its made to 0 otherwise its made to 1.

Matrix after Specification

Degree of node 0 = 2.6
Degree of node 1 = 2.803
Degree of node 2 = 2.55
Degree of node 3 = 3.2
Degree of node 4 = 2.41
Permutation order of objects (R) : 0 2 1 3 4

The new permutation order is just the ordering of the nodes, i.e. convert node ‘R[i]’ to node ‘i’. 
Therefore, convert node ‘R[0] = 0’, to 0; node ‘R[1] = 2’, to 1; node ‘R[2] = 1’, to 2; node ‘R[3] = 3’, to 3; and node ‘R[4] = 4’, to 4;
Let’s take a bigger example to understand the result of the reordering: 

Give a adjacency matrix : 
| 0 1 0 0 0 0 1 0 1 0 |
| 1 0 0 0 1 0 1 0 0 1 |
| 0 0 0 0 1 0 1 0 0 0 |
| 0 0 0 0 1 1 0 0 1 0 |
| 0 1 1 1 0 1 0 0 0 1 |
| 0 0 0 1 1 0 0 0 0 0 |
| 1 1 1 0 0 0 0 0 0 0 |
| 0 0 0 0 0 0 0 0 1 1 |
| 1 0 0 1 0 0 0 1 0 0 |
| 0 1 0 0 1 0 0 1 0 0 |
Degree of node 'A' is defined as number of
nodes connected to 'A'

Output : 
Permutation order of objects (R) :
7 8 9 3 5 1 0 4 6 2

Now convert node ‘R[i]’ to node ‘i’ 
So the graph becomes: 
 

The result of reordering can be seen by the adjacency matrix of the two graph: 
 

Original Matrix

Original Matrix

RCM Reordered Matrix

From here we can clearly see that how the Cuthill-Mckee algorithm helps in the reordering of a square matrix into a non-distributed matrix.

Below is the implementation of the above algorithm. Taking the general definition of degree. 

C++




// C++ program for Implementation of
// Reverse Cuthill Mckee Algorithm
 
#include <bits/stdc++.h>
using namespace std;
 
vector<double> globalDegree;
 
int findIndex(vector<pair<int, double> > a, int x)
{
    for (int i = 0; i < a.size(); i++)
        if (a[i].first == x)
            return i;
    return -1;
}
 
bool compareDegree(int i, int j)
{
    return ::globalDegree[i] < ::globalDegree[j];
}
 
template <typename T>
ostream& operator<<(ostream& out, vector<T> const& v)
{
    for (int i = 0; i < v.size(); i++)
        out << v[i] << ' ';
    return out;
}
 
class ReorderingSSM {
private:
    vector<vector<double> > _matrix;
 
public:
    // Constructor and Destructor
    ReorderingSSM(vector<vector<double> > m)
    {
        _matrix = m;
    }
 
    ReorderingSSM() {}
    ~ReorderingSSM() {}
 
    // class methods
 
    // Function to generate degree of all the nodes
    vector<double> degreeGenerator()
    {
 
        vector<double> degrees;
 
        for (int i = 0; i < _matrix.size(); i++) {
            double count = 0;
            for (int j = 0; j < _matrix[0].size(); j++) {
                count += _matrix[i][j];
            }
 
            degrees.push_back(count);
        }
 
        return degrees;
    }
 
    // Implementation of Cuthill-Mckee algorithm
    vector<int> CuthillMckee()
    {
        vector<double> degrees = degreeGenerator();
 
        ::globalDegree = degrees;
 
        queue<int> Q;
        vector<int> R;
        vector<pair<int, double> > notVisited;
 
        for (int i = 0; i < degrees.size(); i++)
            notVisited.push_back(make_pair(i, degrees[i]));
 
        // Vector notVisited helps in running BFS
        // even when there are dijoind graphs
        while (notVisited.size()) {
 
            int minNodeIndex = 0;
 
            for (int i = 0; i < notVisited.size(); i++)
                if (notVisited[i].second < notVisited[minNodeIndex].second)
                    minNodeIndex = i;
 
            Q.push(notVisited[minNodeIndex].first);
 
            notVisited.erase(notVisited.begin()
                                    + findIndex(notVisited,
                                                notVisited[Q.front()].first));
 
            // Simple BFS
            while (!Q.empty()) {
 
                vector<int> toSort;
 
                for (int i = 0; i < _matrix[0].size(); i++) {
                    if (i != Q.front() && _matrix[Q.front()][i] == 1
                        && findIndex(notVisited, i) != -1) {
                        toSort.push_back(i);
                        notVisited.erase(notVisited.begin()
                                           + findIndex(notVisited, i));
                    }
                }
 
                sort(toSort.begin(), toSort.end(), compareDegree);
 
                for (int i = 0; i < toSort.size(); i++)
                    Q.push(toSort[i]);
 
                R.push_back(Q.front());
                Q.pop();
            }
        }
 
        return R;
    }
 
    // Implementation of reverse Cuthill-Mckee algorithm
    vector<int> ReverseCuthillMckee()
    {
 
        vector<int> cuthill = CuthillMckee();
 
        int n = cuthill.size();
 
        if (n % 2 == 0)
            n -= 1;
 
        n = n / 2;
 
        for (int i = 0; i <= n; i++) {
            int j = cuthill[cuthill.size() - 1 - i];
            cuthill[cuthill.size() - 1 - i] = cuthill[i];
            cuthill[i] = j;
        }
 
        return cuthill;
    }
};
 
// Driver Code
int main()
{
    int num_rows = 10;
 
    vector<vector<double> > matrix;
 
    for (int i = 0; i < num_rows; i++) {
        vector<double> datai;
 
        for (int j = 0; j < num_rows; j++)
            datai.push_back(0.0);
 
        matrix.push_back(datai);
    }
 
    // This is the test graph,
    // check out the above graph photo
    matrix[0] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 };
    matrix[1] = { 1, 0, 0, 0, 1, 0, 1, 0, 0, 1 };
    matrix[2] = { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 };
    matrix[3] = { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 };
    matrix[4] = { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1 };
    matrix[5] = { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 };
    matrix[6] = { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
    matrix[7] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
    matrix[8] = { 1, 0, 0, 1, 0, 0, 0, 1, 0, 0 };
    matrix[9] = { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 };
 
    ReorderingSSM m(matrix);
 
    vector<int> r = m.ReverseCuthillMckee();
 
    cout << "Permutation order of objects: " << r << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.stream.Collectors;
 
public class ReorderingSSM {
 
    private List<List<Double>> matrix;
 
    public ReorderingSSM(List<List<Double>> m) {
        matrix = m;
    }
 
    public ReorderingSSM() {
    }
 
    // Function to generate degree of all the nodes
    private List<Double> DegreeGenerator() {
        List<Double> degrees = new ArrayList<>();
 
        for (int i = 0; i < matrix.size(); i++) {
            double count = 0;
            for (int j = 0; j < matrix.get(0).size(); j++) {
                count += matrix.get(i).get(j);
            }
 
            degrees.add(count);
        }
 
        return degrees;
    }
 
    // Implementation of Cuthill-Mckee algorithm
    private List<Integer> CuthillMckee() {
        List<Double> degrees = DegreeGenerator();
 
        List<Double> globalDegree = new ArrayList<>(degrees);
 
        Queue<Integer> Q = new LinkedList<>();
        List<Integer> R = new ArrayList<>();
        List<Pair<Integer, Double>> notVisited = new ArrayList<>();
 
        for (int i = 0; i < degrees.size(); i++)
            notVisited.add(new Pair<>(i, degrees.get(i)));
 
        // Vector notVisited helps in running BFS
        // even when there are disjoint graphs
        while (!notVisited.isEmpty()) {
            int minNodeIndex = 0;
 
            for (int i = 0; i < notVisited.size(); i++) {
                if (notVisited.get(i).getValue() < notVisited.get(minNodeIndex).getValue())
                    minNodeIndex = i;
            }
 
            Q.add(notVisited.get(minNodeIndex).getKey());
 
            notVisited.remove(FindIndex(notVisited, notVisited.get(Q.peek()).getKey()));
 
            // Simple BFS
            while (!Q.isEmpty()) {
                List<Integer> toSort = new ArrayList<>();
 
                for (int i = 0; i < matrix.get(0).size(); i++) {
                    if (i != Q.peek() && matrix.get(Q.peek()).get(i) == 1
                            && FindIndex(notVisited, i) != -1) {
                        toSort.add(i);
                        notVisited.remove(FindIndex(notVisited, i));
                    }
                }
 
                toSort.sort(Comparator.comparingDouble(globalDegree::get));
 
                Q.addAll(toSort);
 
                R.add(Q.peek());
                Q.poll();
            }
        }
 
        return R;
    }
 
    // Implementation of reverse Cuthill-Mckee algorithm
    private List<Integer> ReverseCuthillMckee() {
        List<Integer> cuthill = CuthillMckee();
 
        int n = cuthill.size();
 
        if (n % 2 == 0)
            n -= 1;
 
        n = n / 2;
 
        for (int i = 0; i <= n; i++) {
            int j = cuthill.get(cuthill.size() - 1 - i);
            cuthill.set(cuthill.size() - 1 - i, cuthill.get(i));
            cuthill.set(i, j);
        }
 
        return cuthill;
    }
 
    // Helper function to find index of an element in a list of pairs
    private int FindIndex(List<Pair<Integer, Double>> a, int x) {
        for (int i = 0; i < a.size(); i++) {
            if (a.get(i).getKey() == x)
                return i;
        }
        return -1;
    }
 
    // Helper function to print a list
    private <T> void PrintList(List<T> list) {
        System.out.println(list.stream().map(Object::toString).collect(Collectors.joining(" ")));
    }
 
    // Driver Code
    public static void main(String[] args) {
        int num_rows = 10;
 
        List<List<Double>> matrix = new ArrayList<>();
 
        for (int i = 0; i < num_rows; i++) {
            List<Double> datai = new ArrayList<>();
 
            for (int j = 0; j < num_rows; j++)
                datai.add(0.0);
 
            matrix.add(datai);
        }
 
        // This is the test graph,
        // check out the above graph photo
        matrix.set(0, List.of(0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0));
        matrix.set(1, List.of(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0));
        matrix.set(2, List.of(0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0));
        matrix.set(3, List.of(0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0));
        matrix.set(4, List.of(0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0));
        matrix.set(5, List.of(0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0));
        matrix.set(6, List.of(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
        matrix.set(7, List.of(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0));
        matrix.set(8, List.of(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0));
        matrix.set(9, List.of(0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0));
 
        ReorderingSSM m = new ReorderingSSM(matrix);
 
        List<Integer> r = m.ReverseCuthillMckee();
 
        System.out.println("Permutation order of objects: ");
        m.PrintList(r);
    }
}
 
class Pair<K, V> {
    private final K key;
    private final V value;
 
    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
 
    public K getKey() {
        return key;
    }
 
    public V getValue() {
        return value;
    }
}


Python3




# C++ program for Implementation of
# Reverse Cuthill Mckee Algorithm
from collections import deque as Queue
 
globalDegree = []
 
 
def findIndex(a, x):
    for i in range(len(a)):
        if a[i][0] == x:
            return i
    return -1
 
 
class ReorderingSSM:
    __matrix = []
    # Constructor and Destructor
    def __init__(self, m):
        self.__matrix = m
 
    # class methods
 
    # Function to generate degree of all the nodes
    def degreeGenerator(self):
 
        degrees = []
 
        for i in range(len(self.__matrix)):
            count = 0
            for j in range(len(self.__matrix[0])):
                count += self.__matrix[i][j]
 
            degrees.append(count)
 
        return degrees
 
    # Implementation of Cuthill-Mckee algorithm
    def CuthillMckee(self):
        global globalDegree
        degrees = self.degreeGenerator()
 
        globalDegree = degrees
 
        Q = Queue()
        R = []
        notVisited = []
 
        for i in range(len(degrees)):
            notVisited.append((i, degrees[i]))
 
        # Vector notVisited helps in running BFS
        # even when there are dijoind graphs
        while len(notVisited):
 
            minNodeIndex = 0
 
            for i in range(len(notVisited)):
                if notVisited[i][1] < notVisited[minNodeIndex][1]:
                    minNodeIndex = i
 
            Q.append(notVisited[minNodeIndex][0])
 
            notVisited.pop(findIndex(notVisited, notVisited[Q[0]][0]))
 
            # Simple BFS
            while Q:
 
                toSort = []
 
                for i in range(len(self.__matrix[0])):
                    if (
                        i != Q[0]
                        and self.__matrix[Q[0]][i] == 1
                        and findIndex(notVisited, i) != -1
                    ):
                        toSort.append(i)
                        notVisited.pop(findIndex(notVisited, i))
 
                toSort.sort(key=lambda x: globalDegree[x])
 
                for i in range(len(toSort)):
                    Q.append(toSort[i])
 
                R.append(Q[0])
                Q.popleft()
 
        return R
 
    # Implementation of reverse Cuthill-Mckee algorithm
    def ReverseCuthillMckee(self):
 
        cuthill = self.CuthillMckee()
 
        n = len(cuthill)
 
        if n % 2 == 0:
            n -= 1
 
        n = n // 2
 
        for i in range(n + 1):
            j = cuthill[len(cuthill) - 1 - i]
            cuthill[len(cuthill) - 1 - i] = cuthill[i]
            cuthill[i] = j
 
        return cuthill
 
 
# Driver Code
if __name__ == "__main__":
    num_rows = 10
 
    matrix = [[0.0] * num_rows for _ in range(num_rows)]
 
    # This is the test graph,
    # check out the above graph photo
    matrix[0] = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0]
    matrix[1] = [1, 0, 0, 0, 1, 0, 1, 0, 0, 1]
    matrix[2] = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0]
    matrix[3] = [0, 0, 0, 0, 1, 1, 0, 0, 1, 0]
    matrix[4] = [0, 1, 1, 1, 0, 1, 0, 0, 0, 1]
    matrix[5] = [0, 0, 0, 1, 1, 0, 0, 0, 0, 0]
    matrix[6] = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
    matrix[7] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
    matrix[8] = [1, 0, 0, 1, 0, 0, 0, 1, 0, 0]
    matrix[9] = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
 
    m = ReorderingSSM(matrix)
 
    r = m.ReverseCuthillMckee()
 
    print("Permutation order of objects:", r)


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class ReorderingSSM
{
    private List<List<double>> matrix;
 
    public ReorderingSSM(List<List<double>> m)
    {
        matrix = m;
    }
 
    public ReorderingSSM() { }
    ~ReorderingSSM() { }
 
    // Function to generate degree of all the nodes
    private List<double> DegreeGenerator()
    {
        List<double> degrees = new List<double>();
 
        for (int i = 0; i < matrix.Count; i++)
        {
            double count = 0;
            for (int j = 0; j < matrix[0].Count; j++)
            {
                count += matrix[i][j];
            }
 
            degrees.Add(count);
        }
 
        return degrees;
    }
 
    // Implementation of Cuthill-Mckee algorithm
    private List<int> CuthillMckee()
    {
        List<double> degrees = DegreeGenerator();
 
        List<double> globalDegree = degrees;
 
        Queue<int> Q = new Queue<int>();
        List<int> R = new List<int>();
        List<Tuple<int, double>> notVisited = new List<Tuple<int, double>>();
 
        for (int i = 0; i < degrees.Count; i++)
            notVisited.Add(new Tuple<int, double>(i, degrees[i]));
 
        // Vector notVisited helps in running BFS
        // even when there are disjoint graphs
        while (notVisited.Count > 0)
        {
            int minNodeIndex = 0;
 
            for (int i = 0; i < notVisited.Count; i++)
            {
                if (notVisited[i].Item2 < notVisited[minNodeIndex].Item2)
                    minNodeIndex = i;
            }
 
            Q.Enqueue(notVisited[minNodeIndex].Item1);
 
            notVisited.RemoveAt(FindIndex(notVisited, notVisited[Q.Peek()].Item1));
 
            // Simple BFS
            while (Q.Count > 0)
            {
                List<int> toSort = new List<int>();
 
                for (int i = 0; i < matrix[0].Count; i++)
                {
                    if (i != Q.Peek() && matrix[Q.Peek()][i] == 1
                        && FindIndex(notVisited, i) != -1)
                    {
                        toSort.Add(i);
                        notVisited.RemoveAt(FindIndex(notVisited, i));
                    }
                }
 
                toSort.Sort((x, y) => globalDegree[x].CompareTo(globalDegree[y]));
 
                foreach (int item in toSort)
                    Q.Enqueue(item);
 
                R.Add(Q.Peek());
                Q.Dequeue();
            }
        }
 
        return R;
    }
 
    // Implementation of reverse Cuthill-Mckee algorithm
    private List<int> ReverseCuthillMckee()
    {
        List<int> cuthill = CuthillMckee();
 
        int n = cuthill.Count;
 
        if (n % 2 == 0)
            n -= 1;
 
        n = n / 2;
 
        for (int i = 0; i <= n; i++)
        {
            int j = cuthill[cuthill.Count - 1 - i];
            cuthill[cuthill.Count - 1 - i] = cuthill[i];
            cuthill[i] = j;
        }
 
        return cuthill;
    }
 
    // Helper function to find index of an element in a list of tuples
    private int FindIndex(List<Tuple<int, double>> a, int x)
    {
        for (int i = 0; i < a.Count; i++)
        {
            if (a[i].Item1 == x)
                return i;
        }
        return -1;
    }
 
    // Helper function to print a list
    private void PrintList<T>(List<T> list)
    {
        Console.WriteLine(string.Join(" ", list));
    }
 
    // Driver Code
    static void Main(string[] args)
    {
        int num_rows = 10;
 
        List<List<double>> matrix = new List<List<double>>();
 
        for (int i = 0; i < num_rows; i++)
        {
            List<double> datai = new List<double>();
 
            for (int j = 0; j < num_rows; j++)
                datai.Add(0.0);
 
            matrix.Add(datai);
        }
 
        // This is the test graph,
        // check out the above graph photo
        matrix[0] = new List<double> { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 };
        matrix[1] = new List<double> { 1, 0, 0, 0, 1, 0, 1, 0, 0, 1 };
        matrix[2] = new List<double> { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 };
        matrix[3] = new List<double> { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 };
        matrix[4] = new List<double> { 0, 1, 1, 1, 0, 1, 0, 0, 0, 1 };
        matrix[5] = new List<double> { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 };
        matrix[6] = new List<double> { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
        matrix[7] = new List<double> { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
        matrix[8] = new List<double> { 1, 0, 0, 1, 0, 0, 0, 1, 0, 0 };
        matrix[9] = new List<double> { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 };
 
        ReorderingSSM m = new ReorderingSSM(matrix);
 
        List<int> r = m.ReverseCuthillMckee();
 
        Console.WriteLine("Permutation order of objects: ");
        m.PrintList(r);
    }
}


Javascript




// JavaScript program for the above approach
 
class Queue {
  constructor() {
    this.items = [];
  }
  enqueue(element) {
    this.items.push(element);
  }
  dequeue() {
    if (this.isEmpty()) return "Underflow";
    return this.items.shift();
  }
  isEmpty() {
    return this.items.length == 0;
  }
}
 
function findIndex(a, x) {
  for (let i = 0; i < a.length; i++) {
    if (a[i][0] == x) {
      return i;
    }
  }
  return -1;
}
 
let globalDegree = [];
 
class ReorderingSSM {
  // Constructor and Destructor
  constructor(m) {
    this.__matrix = m;
  }
     
     
   // class methods
   // Function to generate degree of all the nodes
  degreeGenerator() {
    let degrees = [];
 
    for (let i = 0; i < this.__matrix.length; i++) {
      let count = 0;
      for (let j = 0; j < this.__matrix[0].length; j++) {
        count += this.__matrix[i][j];
      }
      degrees.push(count);
    }
    return degrees;
  }
 
     
  // Implementation of Cuthill-Mckee algorithm
  CuthillMckee() {
    let degrees = this.degreeGenerator();
    globalDegree = degrees;
    let Q = new Queue();
    let R = [];
    let notVisited = [];
 
    for (let i = 0; i < degrees.length; i++) {
      notVisited.push([i, degrees[i]]);
    }
     
    // Vector notVisited helps in running BFS
    // even when there are dijoind graphs
    while (notVisited.length > 0) {
      let minNodeIndex = 0;
 
      for (let i = 0; i < notVisited.length; i++) {
        if (notVisited[i][1] < notVisited[minNodeIndex][1]) {
          minNodeIndex = i;
        }
      }
 
      Q.enqueue(notVisited[minNodeIndex][0]);
      notVisited.splice(findIndex(notVisited, notVisited[Q.items[0]][0]), 1);
     
      // Simple BFS
      while (!Q.isEmpty()) {
        let toSort = [];
 
        for (let i = 0; i < this.__matrix[0].length; i++) {
          if (
            i != Q.items[0] &&
            this.__matrix[Q.items[0]][i] == 1 &&
            findIndex(notVisited, i) != -1
          ) {
            toSort.push(i);
            notVisited.splice(findIndex(notVisited, i), 1);
          }
        }
 
        toSort.sort((a, b) => globalDegree[a] - globalDegree[b]);
 
        for (let i = 0; i < toSort.length; i++) {
          Q.enqueue(toSort[i]);
        }
 
        R.push(Q.items[0]);
        Q.dequeue();
      }
    }
 
    return R;
  }
 
  // Implementation of reverse Cuthill-Mckee algorithm
  ReverseCuthillMckee() {
    let cuthill = this.CuthillMckee();
    let n = cuthill.length;
 
    if (n % 2 == 0) {
      n -= 1;
    }
 
    n = Math.floor(n / 2);
 
    for (let i = 0; i < n + 1; i++) {
      let j = cuthill[cuthill.length - 1 - i];
      cuthill[cuthill.length - 1 - i] = cuthill[i];
      cuthill[i] = j;
    }
 
    return cuthill;
  }
}
 
// Driver code
let num_rows = 10;
let matrix = Array(num_rows)
  .fill()
  .map(() => Array(num_rows).fill(0));
 
// This is the test graph,
// check out the above
    matrix[0] = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0]
    matrix[1] = [1, 0, 0, 0, 1, 0, 1, 0, 0, 1]
    matrix[2] = [0, 0, 0, 0, 1, 0, 1, 0, 0, 0]
    matrix[3] = [0, 0, 0, 0, 1, 1, 0, 0, 1, 0]
    matrix[4] = [0, 1, 1, 1, 0, 1, 0, 0, 0, 1]
    matrix[5] = [0, 0, 0, 1, 1, 0, 0, 0, 0, 0]
    matrix[6] = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
    matrix[7] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
    matrix[8] = [1, 0, 0, 1, 0, 0, 0, 1, 0, 0]
    matrix[9] = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
 
const m = new ReorderingSSM(matrix)
 
const r = m.ReverseCuthillMckee()
 
console.log("Permutation order of objects:", r)
 
// This code is contributed by Prince Kumar


Output

Permutation order of objects: 7 8 9 3 5 1 0 4 6 2 





Last Updated : 09 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads