private void addNodeToRest(DirectedNode node) {
   if (this.nodesSortedByDegree.containsKey(node.getOutDegree())) {
     this.nodesSortedByDegree.get(node.getOutDegree()).add(node);
   } else {
     LinkedList<Node> temp = new LinkedList<Node>();
     temp.add(node);
     this.nodesSortedByDegree.put(node.getOutDegree(), temp);
   }
 }
 private void removeFromRichclub(DirectedNode node) {
   int degree = node.getOutDegree() - 1;
   this.richClub.get(degree).remove(node);
   if (this.richClub.get(degree).isEmpty()) {
     this.richClub.remove(degree);
   }
 }
 private void addToRichClub(DirectedNode node) {
   int degree = node.getOutDegree();
   if (this.richClub.containsKey(degree)) {
     this.richClub.get(degree).add(node);
   } else {
     LinkedList<Node> temp = new LinkedList<Node>();
     temp.add(node);
     this.richClub.put(degree, temp);
   }
 }
  private boolean directedCompute() {

    SortedSet<Integer> degrees = new TreeSet<Integer>();
    for (IElement iE : g.getNodes()) {
      DirectedNode n = (DirectedNode) iE;
      int degree = n.getOutDegree();

      degrees.add(degree);
      if (nodesSortedByDegree.containsKey(degree)) {
        this.nodesSortedByDegree.get(degree).add(n);
      } else {
        LinkedList<Node> temp = new LinkedList<>();
        temp.add(n);
        this.nodesSortedByDegree.put(degree, temp);
      }
    }

    HashSet<Node> currentRichClub = new HashSet<Node>();
    int currentRichClubSize = 0;
    int size = degrees.size();
    for (int i = 0; i < size; i++) {
      int currentDegree = degrees.last();
      degrees.remove(currentDegree);
      LinkedList<Node> current = this.nodesSortedByDegree.get(currentDegree);
      currentRichClubSize += current.size();
      this.nodesSortedByDegree.remove(currentDegree);

      if (currentRichClubSize >= this.richClubSize) {
        int seperateAT = current.size() - (currentRichClubSize - this.richClubSize);
        LinkedList<Node> temp = new LinkedList<>();
        temp.addAll(current.subList(0, seperateAT));
        this.richClub.put(currentDegree, temp);
        currentRichClub.addAll(temp);
        LinkedList<Node> temp2 = new LinkedList<>();
        temp2.addAll(current.subList(seperateAT, current.size()));
        if (!temp2.isEmpty()) this.nodesSortedByDegree.put(currentDegree, (LinkedList<Node>) temp2);
        break;
      } else {
        richClub.put(currentDegree, current);
        currentRichClub.addAll(current);
      }
    }

    for (Node n : currentRichClub) {
      DirectedNode ne = (DirectedNode) n;
      for (IElement iE : ne.getOutgoingEdges()) {
        DirectedEdge e = (DirectedEdge) iE;
        if (currentRichClub.contains(e.getDst())) {
          edgesBetweenRichClub++;
        }
      }
    }
    return true;
  }
  private boolean applyAfterDirectedEdgeAddition(Update u) {
    DirectedEdge e = (DirectedEdge) ((EdgeUpdate) u).getEdge();
    DirectedNode src = e.getSrc();
    DirectedNode dst = e.getDst();
    int srcDegree = src.getOutDegree();
    int dstDegree = dst.getOutDegree();

    if (richClub.containsKey(srcDegree - 1) && richClub.get(srcDegree - 1).contains(src)) {

      if (richClub.containsKey(dstDegree) && richClub.get(dstDegree).contains(dst)) {
        this.edgesBetweenRichClub++;
      }
      removeFromRichclub(src);
      addToRichClub(src);
    } else if (this.richClub.containsKey(srcDegree - 1)
        && this.nodesSortedByDegree.containsKey(srcDegree - 1)
        && this.nodesSortedByDegree.get(srcDegree - 1).contains(src)) {

      // changes for lastNode of Richclub
      DirectedNode lastNode = (DirectedNode) this.richClub.get(srcDegree - 1).removeLast();
      if (this.richClub.get(lastNode.getOutDegree()).isEmpty()) {
        this.richClub.remove(lastNode.getOutDegree());
      }
      addNodeToRest(lastNode);

      // Changes for src node for richclub
      this.nodesSortedByDegree.get(srcDegree - 1).remove(src);
      if (this.nodesSortedByDegree.get(src.getOutDegree() - 1).isEmpty()) {
        this.nodesSortedByDegree.remove(src.getOutDegree() - 1);
      }
      addToRichClub(src);

      // calculate changes for richclub connectivity
      for (IElement ie : src.getEdges()) {
        DirectedEdge edge = (DirectedEdge) ie;
        DirectedNode node = (DirectedNode) edge.getDifferingNode(src);
        if (this.richClub.containsKey(node.getOutDegree())
            && this.richClub.get(node.getOutDegree()).contains(node)) {
          this.edgesBetweenRichClub++;
        }
      }

      for (IElement ie : lastNode.getEdges()) {
        DirectedEdge edge = (DirectedEdge) ie;
        DirectedNode node = (DirectedNode) edge.getDifferingNode(lastNode);
        if (this.richClub.containsKey(node.getOutDegree())
            && this.richClub.get(node.getOutDegree()).contains(node)) {
          this.edgesBetweenRichClub--;
        }
      }

    } else {
      this.nodesSortedByDegree.get(src.getOutDegree() - 1).remove(src);
      if (this.nodesSortedByDegree.get(src.getOutDegree() - 1).isEmpty()) {
        this.nodesSortedByDegree.remove(src.getOutDegree() - 1);
      }
      addNodeToRest(src);
    }
    return true;
  }
  private boolean applyAfterDirectedNodeRemoval(Update u) {
    DirectedNode node = (DirectedNode) ((NodeRemoval) u).getNode();
    int min = Integer.MAX_VALUE;
    int max = 0;
    HashMap<Integer, LinkedList<DirectedNode>> order = new HashMap<>();
    for (IElement ie : node.getIncomingEdges()) {
      DirectedEdge e = (DirectedEdge) ie;
      DirectedNode n = e.getSrc();

      if (richClub.containsKey(n.getOutDegree() + 1)
          && richClub.get(n.getOutDegree() + 1).contains(n)) {
        this.edgesBetweenRichClub--;
        min = Math.min(min, n.getOutDegree());
        max = Math.max(max, n.getOutDegree());
        richClub.get(n.getOutDegree() + 1).remove(n);
        if (richClub.get(n.getOutDegree() + 1).isEmpty()) {
          richClub.remove(n.getOutDegree() + 1);
        }
        if (richClub.containsKey(n.getOutDegree())) {
          richClub.get(n.getOutDegree()).add(n);
        } else {
          richClub.put(n.getOutDegree(), new LinkedList<Node>());
          richClub.get(n.getOutDegree()).add(n);
        }
        if (order.containsKey(n.getOutDegree())) {
          order.get(n.getOutDegree()).add(n);
        } else {
          order.put(n.getOutDegree(), new LinkedList<DirectedNode>());
          order.get(n.getOutDegree()).add(n);
        }
      } else if (nodesSortedByDegree.containsKey(n.getOutDegree() + 1)
          && nodesSortedByDegree.get(n.getOutDegree() + 1).contains(n)) {
        nodesSortedByDegree.get(n.getOutDegree() + 1).remove(n);
        if (nodesSortedByDegree.get(n.getOutDegree() + 1).isEmpty()) {
          nodesSortedByDegree.remove(n.getOutDegree() + 1);
        }
        if (nodesSortedByDegree.containsKey(n.getOutDegree())) {
          nodesSortedByDegree.get(n.getOutDegree()).add(n);
        } else {
          nodesSortedByDegree.put(n.getOutDegree(), new LinkedList<Node>());
          nodesSortedByDegree.get(n.getOutDegree()).add(n);
        }
      } else {
        System.out.println("f**k");
      }
    }

    for (int i = min; i <= max; i++) {
      boolean f = false;
      if (f) {
        break;
      }
      if (!order.containsKey(i)) {
        continue;
      }
      for (DirectedNode n1 : order.get(i)) {
        int big = getBiggest();
        if (i >= big) {
          f = true;
          break;
        }

        // changes for firstNode of Rest
        DirectedNode firstNode = (DirectedNode) this.nodesSortedByDegree.get(big).removeFirst();
        if (this.nodesSortedByDegree.get(firstNode.getOutDegree()).isEmpty()) {
          this.nodesSortedByDegree.remove(firstNode.getOutDegree());
        }
        addToRichClub(firstNode);

        // Changes for src node for richclub
        this.richClub.get(i).remove(n1);
        if (this.richClub.get(i).isEmpty()) {
          this.richClub.remove(i);
        }
        addNodeToRest(n1);

        // calculate changes for richclub connectivity
        for (IElement ie : n1.getEdges()) {
          DirectedEdge edge = (DirectedEdge) ie;
          DirectedNode n2 = (DirectedNode) edge.getDifferingNode(n1);
          if (this.richClub.containsKey(n2.getOutDegree())
              && this.richClub.get(n2.getOutDegree()).contains(n2)) {
            this.edgesBetweenRichClub--;
          }
        }

        for (IElement ie : firstNode.getEdges()) {
          DirectedEdge edge = (DirectedEdge) ie;
          DirectedNode n2 = (DirectedNode) edge.getDifferingNode(firstNode);
          if (this.richClub.containsKey(n2.getOutDegree())
              && this.richClub.get(n2.getOutDegree()).contains(n2)) {
            this.edgesBetweenRichClub++;
          }
        }
      }
    }
    if (this.richClub.containsKey(node.getOutDegree())
        && this.richClub.get(node.getOutDegree()).contains(node)) {
      int degree = ((DirectedNode) node).getOutDegree();

      // changes for firstNode of Rest
      DirectedNode firstNode =
          (DirectedNode) this.nodesSortedByDegree.get(getBiggest()).removeFirst();
      if (this.nodesSortedByDegree.get(firstNode.getOutDegree()).isEmpty()) {
        this.nodesSortedByDegree.remove(firstNode.getOutDegree());
      }
      addToRichClub(firstNode);

      // Changes for src node for richclub
      this.richClub.get(degree).remove(node);
      if (this.richClub.get(degree).isEmpty()) {
        this.richClub.remove(degree);
      }

      // calculate changes for richclub connectivity
      for (IElement ie : node.getOutgoingEdges()) {
        DirectedEdge edge = (DirectedEdge) ie;
        DirectedNode n2 = (DirectedNode) edge.getDifferingNode(node);
        if (this.richClub.containsKey(n2.getOutDegree())
            && this.richClub.get(n2.getOutDegree()).contains(n2)) {
          this.edgesBetweenRichClub--;
        }
      }

      for (IElement ie : firstNode.getEdges()) {
        DirectedEdge edge = (DirectedEdge) ie;
        DirectedNode n2 = (DirectedNode) edge.getDifferingNode(firstNode);
        if (this.richClub.containsKey(n2.getOutDegree())
            && this.richClub.get(n2.getOutDegree()).contains(n2)) {
          this.edgesBetweenRichClub++;
        }
      }

    } else {
      int degree = ((DirectedNode) node).getOutDegree();

      this.nodesSortedByDegree.get(degree).remove(node);
      if (this.nodesSortedByDegree.get(degree).isEmpty()) {
        this.nodesSortedByDegree.remove(degree);
      }
    }

    return true;
  }