A graph data structure is a collection of nodes that have data and are connected to other nodes.
Let’s try to understand this through an example. On facebook, everything is a node. That includes User, Photo, Album, Event, Group, Page, Comment, Story, Video, Link, Note…anything that has data is a node.
Every relationship is an edge from one node to another. Whether you post a photo, join a group, like a page, etc., a new edge is created for that relationship.
A graph is a pair (V, E), where V is a set of nodes, called vertices, and E is a collection of pairs of vertices, called edges.
representing dependency of tables in databases
Tree is a data structure similar to a linked list but instead of each node pointing simply to the next node in a linear fashion, each node points to a number of nodes. Tree is an example of non- linear data structures. A tree structure is a way of representing the hierarchical nature of a structure in a graphical form.
A tree
is a collection of entities called nodes
. Nodes are connected by edges
. Each node
contains a value
or data
, and it may or may not have a child node
The first node
of the tree
is called the root
. If this root node
is connected by another node
, the root
is then a parent node
and the connected node
is a child
.
node
of the tree
nodes
node
that has a parent node
node
that has an edge
to a child node
node
that does not have a child node
in the tree
leaf
root
A general tree is a tree data structure where there are no constraints on the hierarchical structure.
A tree is called binary tree if each node has zero child, one child or two children. Empty tree is also a valid binary tree. We can visualize a binary tree as consisting of a root and two disjoint binary trees, called the left and right subtrees of the root.
A left child precedes a right child in the order of children of a node. Or in other others, left side of tree is small than right side of tree
Note that Strict Binary Tree is a binary tree with each node has exactly two children or no children.
A binary tree is called full binary tree if each node has exactly two children and all leaf nodes are at the same level.
A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.
2. All nodes are filled starting from left
Following are the some of the applications where binary trees play an important role:
@NoArgsConstructor @AllArgsConstructor @Data @ToString public class TreeNode { private User data; private TreeNode left; private TreeNode right; public TreeNode(User data) { this.data = data; } } @ToString @NoArgsConstructor @AllArgsConstructor @Data class User implements Serializable, Comparable<User> { /** * */ private static final long serialVersionUID = 1L; private String name; private Integer rating; @Override public int compareTo(User other) { // TODO Auto-generated method stub return this.rating.compareTo(other.getRating()); } }
public TreeNode insert(TreeNode parent, User data) { /** * if node is null, put the data there */ if (parent == null) { return new TreeNode(data); } User parentData = parent.getData(); /** * if parent is greater than new node, go left<br> * if parent is less than new node, go right<br> */ if (parentData.getRating() > data.getRating()) { parent.setLeft(insert(parent.getLeft(), data)); } else { parent.setRight(insert(parent.getRight(), data)); } return parent; } public TreeNode insert(User data) { if(root==null) { root = new TreeNode(data); return root; } return insert(root,data); }
public class BinaryTreeMain { public static void main(String[] args) { // TODO Auto-generated method stub TreeNode root = new TreeNode(); root.setData(new User("Folau", 20)); BinaryTree binaryTree = new BinaryTree(root); binaryTree.insert(new User("Lisa", 30)); binaryTree.insert(new User("Laulau", 15)); binaryTree.insert(new User("Kinga", 12)); binaryTree.insert(new User("Fusi", 35)); binaryTree.insert(new User("Nesi", 34)); binaryTree.insert(new User("Melenesi", 32)); System.out.println("PreOrder Traversal"); binaryTree.preOrder(root, "root"); System.out.println("InOrder Traversal"); binaryTree.inOrder(root); System.out.println("PostOrder Traversal"); binaryTree.postOrder(root); } }
PreOrder Traversal root - User(name=Folau, rating=20) left - User(name=Laulau, rating=15) left - User(name=Kinga, rating=12) right - User(name=Lisa, rating=30) right - User(name=Fusi, rating=35) left - User(name=Nesi, rating=34) left - User(name=Melenesi, rating=32) InOrder Traversal User(name=Kinga, rating=12) User(name=Laulau, rating=15) User(name=Folau, rating=20) User(name=Lisa, rating=30) User(name=Melenesi, rating=32) User(name=Nesi, rating=34) User(name=Fusi, rating=35) PostOrder Traversal User(name=Kinga, rating=12) User(name=Laulau, rating=15) User(name=Melenesi, rating=32) User(name=Nesi, rating=34) User(name=Fusi, rating=35) User(name=Lisa, rating=30) User(name=Folau, rating=20)
Now that inserting elements into binary tree is done. We have ways to navigate through or traverse a tree data structure.
We have two options. Breadth-First Search(BFS) and Depth-First Search(DFS)
DFS is an algorithm for traversing or searching tree data structure. One starts at the root and explores as far as possible along each branch before backtracking.
DFS explores a path all the way to a leaf before backtracking and exploring another path. There 3 types of DFS: pre-order
, in-order
, and post-order
Time Complexity: O(n). Space Complexity: O(n)
/** * 1. Traverse the left subtree in Inorder.<br> * 2. Visit the root.<br> * 3. Traverse the right subtree in Inorder.<br> * Time Complexity: O(n). Space Complexity: O(n).<br> */ public void inOrder(TreeNode node) { if (node != null) { inOrder(node.getLeft()); System.out.println(node.getData().toString()); inOrder(node.getRight()); } }
Time Complexity: O(n). Space Complexity: O(n)
/** * 1. Visit the root.<br> * 2. Traverse the left subtree in Preorder.<br> * 3. Traverse the right subtree in Preorder.<br> * Time Complexity: O(n). Space Complexity: O(n). */ public void preOrder(TreeNode node) { if (node != null) { System.out.println(node.getData().toString()); preOrder(node.getLeft()); preOrder(node.getRight()); } }
Time Complexity: O(n). Space Complexity: O(n).
/** * 1. Traverse the left subtree in Postorder.<br> * 2. Traverse the right subtree in Postorder.<br> * 3. Visit the root.<br> * Time Complexity: O(n). Space Complexity: O(n).<br> */ public void postOrder(TreeNode node) { if (node != null) { postOrder(node.getLeft()); postOrder(node.getRight()); System.out.println(node.getData().toString()); } }
Breadth-First Search
BFS is an algorithm for traversing or searching tree data structure. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors.
BFS algorithm traverses the tree
level by level and depth by depth.
public void bfs() { int level = 1; queue.add(new LevelNode(root, level)); while (queue.isEmpty() != true) { LevelNode levelNode = queue.poll(); TreeNode node = levelNode.getNode(); level++; // 1. process node System.out.println("level: "+levelNode.getLevel()+", data: "+ node.getData().toString()); // 2. push left and right child nodes onto queue if(node.getLeft()!=null) { queue.add(new LevelNode(node.getLeft(), level)); } if(node.getRight()!=null) { queue.add(new LevelNode(node.getRight(), level)); } } }
Heap is a tree-based data structure in which all the nodes of the tree are in a specific order. Heap is a complete binary tree-based data structure. Heaps have specific ordering properties. The ordering can be one of two types:
35 33 42 10 14 19 27 44 26 31
Max-Heap construction
Max-Heap deletion
@NoArgsConstructor @AllArgsConstructor @Data @ToString public class MaxHeap { private List<Integer> data = new ArrayList<>(); /** * Function to return the position of the parent for the node currently at position */ private int parent(int position) { if (position == 0) { return 0; } return (position - 1) / 2; } /** * Function to return the position of the left child for the node currently at position */ private int left(int position) { return (2 * position) + 1; } /** * Function to return the position of the right child for the node currently at position */ private int right(int position) { return (2 * position) + 2; } private void swap(int firstPosition, int secondPosition) { System.out.println("firstPosition: " + firstPosition + ", data: " + this.data.get(firstPosition) + ", secondPosition: " + secondPosition + ", data: " + this.data.get(secondPosition)); int tmp = this.data.get(firstPosition); this.data.set(firstPosition, this.data.get(secondPosition)); this.data.set(secondPosition, tmp); System.out.println("firstPosition: " + firstPosition + ", data: " + this.data.get(firstPosition) + ", secondPosition: " + secondPosition + ", data: " + this.data.get(secondPosition)); } public void add(int item) { this.data.add(item); // increase the size of an array Heap[++size] = element; int current = getSize() - 1; System.out.println("adding: " + item + " to position: " + current); heapifyUp(current); } public int peek() { return data.get(0); } /** * Step 1 − Remove root node.<br> * Step 2 − Move the last element of last level to root.<br> * Step 3 − Compare the value of this child node with its parent.<br> * Step 4 − If value of parent is less than child, then swap them.<br> * Step 5 − Repeat step 3 & 4 until Heap property holds.<br> */ public int poll() { int head = data.get(0); // replace the root of the heap with the last element data.set(0, this.data.get(getSize() - 1)); data.remove(getSize() - 1); // call heapify-down on the root node heapifyDown(0); return head; } /** * Step 1 − Create a new node at the end of heap.<br> * Step 2 − Assign new value to the node.<br> * Step 3 − Compare the value of this child node with its parent.<br> * Step 4 − If value of parent is less than child, then swap them.<br> * Step 5 − Repeat step 3 & 4 until Heap property holds.<br> */ private void heapifyUp(int position) { int temp = this.data.get(position); if (position > 0 && temp > this.data.get(parent(position))) { System.out.println("heapifyUp - position: " + position + ", data: " + this.data.get(parent(position))); // swap the two if heap property is violated swap(position, parent(position)); // call heapify-up on the parent heapifyUp(parent(position)); } } /** * Step 1 − Remove root node.<br> * Step 2 − Move the last element of last level to root.<br> * Step 3 − Compare the value of this child node with its parent.<br> * Step 4 − If value of parent is less than child, then swap them.<br> * Step 5 − Repeat step 3 & 4 until Heap property holds.<br> */ private void heapifyDown(int position) { int largest = position; int leftChild = left(position); int rightChild = right(position); // compare `A[i]` with its left and right child // and find the largest value int size = getSize(); if (leftChild < size && this.data.get(leftChild) > this.data.get(largest)) { largest = leftChild; } if (rightChild < size && this.data.get(rightChild) > this.data.get(largest)) { largest = rightChild; } if (largest != position) { // swap with a child having lesser value swap(position, largest); // call heapify-down on the child heapifyDown(largest); } } public void print() { System.out.println("\nList"); for (Integer d : data) { System.out.println("data: " + d); } System.out.println("\nTree"); System.out.println("Root: " + data.get(0)); for (int i = 1; i <= getSize() / 2; i++) { try { System.out.print("Parent: " + this.data.get(i - 1)); } catch (Exception e) { } try { System.out.print(", Left: " + this.data.get(this.left(i - 1))); } catch (Exception e) { } try { System.out.print(", Right: " + this.data.get((this.right(i - 1)))); } catch (Exception e) { } System.out.println(); } System.out.println("\n"); } public int getSize() { return this.data.size(); } }
35 33 42 10 14 19 27 44 26 31
@NoArgsConstructor @AllArgsConstructor @Data @ToString public class MinHeap { private List<Integer> data = new ArrayList<>(); /** * Function to return the position of the parent for the node currently at position */ private int parent(int position) { if (position == 0) { return 0; } return (position - 1) / 2; } /** * Function to return the position of the left child for the node currently at position */ private int left(int position) { return (2 * position) + 1; } /** * Function to return the position of the right child for the node currently at position */ private int right(int position) { return (2 * position) + 2; } private void swap(int firstPosition, int secondPosition) { System.out.println("firstPosition: " + firstPosition + ", data: " + this.data.get(firstPosition) + ", secondPosition: " + secondPosition + ", data: " + this.data.get(secondPosition)); int tmp = this.data.get(firstPosition); this.data.set(firstPosition, this.data.get(secondPosition)); this.data.set(secondPosition, tmp); System.out.println("firstPosition: " + firstPosition + ", data: " + this.data.get(firstPosition) + ", secondPosition: " + secondPosition + ", data: " + this.data.get(secondPosition)); } public void add(int item) { this.data.add(item); // increase the size of an array Heap[++size] = element; int current = getSize() - 1; System.out.println("adding: " + item + " to position: " + current); heapifyUp(current); } public int peek() { return data.get(0); } public int poll() { int head = data.get(0); // replace the root of the heap with the last element data.set(0, this.data.get(getSize() - 1)); data.remove(getSize() - 1); // call heapify-down on the root node heapifyDown(0); return head; } /** * Step 1 − Create a new node at the end of heap.<br> * Step 2 − Assign new value to the node.<br> * Step 3 − Compare the value of this child node with its parent.<br> * Step 4 − If value of parent is greater than child, then swap them.<br> * Step 5 − Repeat step 3 & 4 until Heap property holds.<br> */ private void heapifyUp(int position) { int temp = this.data.get(position); if (position > 0 && temp < this.data.get(parent(position))) { System.out.println("heapifyUp - position: " + position + ", data: " + this.data.get(parent(position))); // swap the two if heap property is violated swap(position, parent(position)); // call heapify-up on the parent heapifyUp(parent(position)); } } /** * Step 1 − Remove root node.<br> * Step 2 − Move the last element of last level to root.<br> * Step 3 − Compare the value of this child node with its parent.<br> * Step 4 − If value of parent is greater than child, then swap them.<br> * Step 5 − Repeat step 3 & 4 until Heap property holds.<br> */ private void heapifyDown(int position) { int smallest = position; int leftChild = left(position); int rightChild = right(position); // compare `A[i]` with its left and right child // and find the smallest value int size = getSize(); if (leftChild < size && this.data.get(leftChild) < this.data.get(smallest)) { smallest = leftChild; } if (rightChild < size && this.data.get(rightChild) < this.data.get(smallest)) { smallest = rightChild; } if (smallest != position) { // swap with a child having lesser value swap(position, smallest); // call heapify-down on the child heapifyDown(smallest); } } public void print() { System.out.println("\nList"); for (Integer d : data) { System.out.println("data: " + d); } System.out.println("\nTree"); System.out.println("Root: " + data.get(0)); for (int i = 1; i <= getSize() / 2; i++) { try { System.out.print("Parent: " + this.data.get(i - 1)); } catch (Exception e) { } try { System.out.print(", Left: " + this.data.get(this.left(i - 1))); } catch (Exception e) { } try { System.out.print(", Right: " + this.data.get((this.right(i - 1)))); } catch (Exception e) { } System.out.println(); } System.out.println("\n"); } public int getSize() { return this.data.size(); } }
CSS (Cascading Style Sheets) is used to style and lay out web pages — for example, to alter the font, color, size, and spacing of your content, split it into multiple columns, or add animations and other decorative features. It is a simple design language intended to simplify the process of making web pages presentable.
CSS handles the look and feel part of a web page. Using CSS, you can control the color of the text, the style of fonts, the spacing between paragraphs, how columns are sized and laid out, what background images or colors are used, layout designs,variations in display for different devices and screen sizes as well as a variety of other effects.
CSS is easy to learn and understand but it provides powerful control over the presentation of an HTML document. Most commonly, CSS is combined with the markup languages HTML or XHTML.
How does CSS work?
When a browser displays a document, it must combine the document’s content with its style information. It processes the document in a number of stages, which we’ve listed below. Bear in mind that this is a very simplified version of what happens when a browser loads a webpage, and that different browsers will handle the process in different ways. But this is roughly what happens.
What happens if CSS has an error?
The answer is that it does nothing, and just moves on to the next bit of CSS!
If a browser is parsing your rules, and encounters a property or value that it doesn’t understand, it ignores it and moves on to the next declaration. It will do this if you have made an error and misspelled a property or value, or if the property or value is just too new and the browser doesn’t yet support it.
Similarly, if a browser encounters a selector that it doesn’t understand, it will just ignore the whole rule and move on to the next one.
List all branches within a repository
git branch //or git branch --list
List all of remote branches
git branch -a
Create a local branch
git branch {branch-name}
Example: create a branch name test-100
git branch test-100
Check for the new created branch
folaukaveinga@Folaus-MacBook-Pro-3 demo % git branch develop master test-100
Push new local branch to remote
git push --set-upstream origin {branch-name}
Delete local branch
Use -d for safe delete. This means that if there are changes or commits in the branch that have not been commited or pushed up to remote, delete won’t work.
git branch -d {branch-name}
Use -D to force delete the specified branch, even if it has unmerged changes.
git branch -D {branch-name}
Delete a remote branch
git push origin --delete {branch-name}
Rename a branch locally
if you want to rename the branch remotely, Use push origin to reflect the change remotely.
git branch -m {new-branch-name}
Pull a remote branch to local
When you want to pull a remote branch to your local.
git pull origin {remote-branch-name} // and git checkout {remote-branch-name}