// The Function That Calculates The Minimum Spanning Tree For The Graph // Its Only Parameter Is The List Of Distinct Colors public void MinSpanningTree(List <RGBPixel> LoD) { // Using A Priority Queue So That The Edges Are // Sorted According To Their Weights In Ascending Order // The Priority Queue Contains The Number Of Vertices (LoD.Count) FastPriorityQueue <PQNode> PQ = new FastPriorityQueue <PQNode>(LoD.Count); // An Array That Contains Each Node (color) // And A Pointer To That Node's Parent PQNode[] PQNode = new PQNode[LoD.Count]; // Initialising The First Node In The Array // Its Parent Is Null PQNode[0] = new PQNode(LoD[0], null); // Inserting That First Node Into The Priority Queue // With A Value of 0 PQ.Enqueue(PQNode[0], 0); float weight; // For Each Vertex (Minus The Already Added One), // Insert That Vertex Into The Array // With Parent = null, Then Insert It Into The PQ // With Values = Infinity for (int i = 1; i < LoD.Count; i++) { PQNode[i] = new PQNode(LoD[i], null); PQ.Enqueue(PQNode[i], int.MaxValue); } // Looping Until The Priority Queue Is Empty while (PQ.Count != 0) { // Dequeuing The First (Minimum) Element // From The PQ PQNode Minimum = PQ.Dequeue(); // Checking If The Minimum Element Is The Root Node Or Not // (Only The Root Node Has A Null Parent In The First Iteration) if (Minimum.Parent != null) { Edge edge; edge.src = Minimum.currentVertex; edge.dest = (RGBPixel)Minimum.Parent; edge.weight = (Minimum.currentWeight); MST.Add(edge); // Add the minimum weight to the MST. MSTSum += edge.weight; // Add The Edge's Weight To The MST Sum } // We Have To Modify The Values Of The PQ // Each Time foreach (var node in PQ) { // Calculating The Weight Difference Between The Current Node // And The Minimum Node weight = WeightDifference(node, Minimum); // If That Weight Difference Is Less Than The Node's Current Weight // Then The Minimum Node Becomes The Parent Of That Node // And We Adjust That Node's Weight To The Weight Difference // By Updating The PQ if (weight < node.currentWeight) { node.Parent = Minimum.currentVertex; PQ.UpdatePriority(node, weight); } } } }
} //get_distincit public static void grph(int CLUS)// graph construction and getting edges that will be cut that take number of clusters { /* * Total complexty = O (E log (k)) * --where E is the number of edges and K is the number of clusters wanted to cut */ float min = 10000000, newedge; //min is minimum value that take from moving from exesting node to another node, newedge is edge between exesting node to another node int k = 0, count = nodes.Count; //k is the index of minimum node that i would start in next time bool[] vstd = new bool[16777216]; //to check if node has been visited before (get values between it and all another none visited nodes) VX = new Dictionary <GRAPH, float>(); // initialize th helper of periority_queue H = new FastPriorityQueue <GRAPH>(CLUS - 1); //initialize periority_queue for (int i = k; ;) //first loop to move in distincit node { bool ch = false; // if it still false then i can't go anywhere because all nodes have been visited if (vstd[nodes[i]]) { continue; // if the node that i stand in is visited then continue } vstd[nodes[i]] = true; //this not is not visited before then make it as visited min = 10000000; // give minimum every time very large value for (int j = 0; j < count; j++) //second loop to move in distincit node { if (vstd[nodes[j]]) { continue; //if the node that i stand in is visited then continue } ch = true; //then it i found another node to move in byte[] b = BitConverter.GetBytes(nodes[i]), bb = BitConverter.GetBytes(nodes[j]); // convert the shifted integer to red and green and blue newedge = (((b[0] - bb[0]) * (b[0] - bb[0])) + ((b[1] - bb[1]) * (b[1] - bb[1])) + ((b[2] - bb[2]) * (b[2] - bb[2]))); //calculate the edge between to nodes if (newedge < min) //if the edge i have less than minimum then { min = newedge; //make the minimum is newedge k = j; //and save its index to start from it the next time } if (MST[j].edge < min) // if the edge that is already saved is less than minimum then { min = MST[j].edge; //make the minimum is saved edge k = j; //and save its index to start from it the next time } if (newedge < (float)MST[j].edge) // if the calculated edge before is larger than the newly calculated edge then { MST[j].edge = newedge; //then replace the calculaed edge with the new minimum edge MST[j].from = nodes[i]; //and change from where it comes } } i = k; //K is the minimum index that i will start the loop with if (ch == false) // then i cant go to any node again because all nodes have been visited then choose the cutted edges { GRAPH T = new GRAPH(); //temp to delete the deleted edge from dictionary as it is deleted from periority_queue for (int y = 1; y < MST.Count; y++) //move in all Minimum spanning tree { if (H.Count < CLUS - 1) // if the periority_queue is not filled with required number of clusters then { H.Enqueue(MST[y], MST[y].edge); // add in periority_queue with complexty O(log K) k is the wanted number of clusters VX.Add(MST[y], MST[y].edge); // add in the dictionary this edge } else//if the periority_queue is filled with required number of clusters then { if (H.First.edge < MST[y].edge) //check if the edge that i stand is larger than the top of queue that contain the smallest edge { T = H.Dequeue(); //pop the smallest from the queue VX.Remove(T); //remove also this node from dictionary H.Enqueue(MST[y], MST[y].edge); //enqueue the new large node with the new large edge with complexty O(log K) VX.Add(MST[y], MST[y].edge); //add the new large node with the new large edge } } } } if (!ch) { break; //if i can't go anywhere then break } }//main loop /* this to get cost of minimum spanning tree*/ /* double sum = 0; * for (int i = 1; i < MST.Count; i++) * { * sum += Math.Sqrt(MST[i].edge); * } * MessageBox.Show(sum.ToString());*/ }