Introducing the Rope data structure 2 – Arrays, collections and data structures

0 Comments 7:07 AM
Implementing concat(Node node1, Node node2)

Concatenating two Ropes (node1 and node2) is a straightforward step-by-step algorithm:

Create a new root node having the weight of the leaf nodes in node1

The new root node has node1 as its left child and node2 as is right child

Optional rebalancing (not implemented here, but is a classic binary tree rebalancing)

The following diagram represents the concatenation of two Ropes:

Figure 5.15 – Concatenating two ropes

In code lines, we have:

public static Node concat(Node node1, Node node2) {
  return new Node(node1, node2, getLength(node1));
}
private static int getLength(Node node) {
  if (node.str != null) {
    return node.weight;
  } else {
    return getLength(node.left) + (node.right == null ?
      0 : getLength(node.right));
  }
}

Next, let’s insert a new node.

Implementing insert(Node node, int index, String str)

In order to insert a piece of string at a certain index in the original string we have to split the original string and perform two concatenations. The algorithm has three steps as follows:

Split the original string at index in two strings, s1, and s2
Concatenate s1 and the given str into s3
Concatenate s1 with the new s3

In code lines, we have the following implementation:

public static Node insert(Node node, int index, String str) {
  List<Node> splitRopes = Rope.split(node, index);
  Node insertNode = new Node(null, null, str.length(), str);
  Node resultNode;
  if (splitRopes.size() == 1) {
    if (index == 0) {
      resultNode = Rope.concat(insertNode, splitRopes.get(0));
    } else {
      resultNode = Rope.concat(splitRopes.get(0), insertNode);
    }
  } else {                        
   resultNode = Rope.concat(splitRopes.get(0), insertNode);
   resultNode = Rope.concat(resultNode, splitRopes.get(1));
  }
  return resultNode;
}

Next, let’s see how to delete a substring.

Implementing delete(Node node, int start, int end)

Deleting a substring from the original string between start and end requires two splits and one concatenation. The algorithm consists of three steps as follows:

Split the original string at start into s1 and s2

Split s2 at end into s3 and s4

Concatenate s1 and s4

In code lines, we have the following implementation:

public static Node delete(Node node, int start, int end) {
  Node beforeNode = null;
  Node afterNode;
  List<Node> splitRopes1 = Rope.split(node, start);
  if (splitRopes1.size() == 1) {
    afterNode = splitRopes1.get(0);
  } else {
    beforeNode = splitRopes1.get(0);
    afterNode = splitRopes1.get(1);
  }
  List<Node> splitRopes2 = Rope.split(afterNode, end – start);
  if (splitRopes2.size() == 1) {
    return beforeNode;
  }
  return beforeNode == null ? splitRopes2.get(1) :
    Rope.concat(beforeNode, splitRopes2.get(1));
}

Finally, let’s talk about splitting a Rope.

Implementing split(Node node, int index)

Splitting a Rope into two Ropes is an operation that should consider two cases of splitting a leaf node:

Split should take place at the last character (index)

Split should take place at the middle character (index)

Both of these cases are considered in the implementation listed in the bundled code. Since this code is simple but quite large, we skipped it here for brevity reasons.

Leave a Reply

Your email address will not be published. Required fields are marked *

Dissecting factory methods for collections – Arrays, collections and data structuresDissecting factory methods for collections – Arrays, collections and data structures

109. Dissecting factory methods for collections Factory methods for collections are a must-have skill. Is very convenient to be able to quickly and effortlessly create and populate unmodifiable/immutable collections before

Adding more artifacts in a record Certification Exams of Java Getting a list from a stream Java Exams Tackling guarded record patterns Tackling records in Spring Boot Understanding records serialization