Skip to main content
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 3/
  5. Data Structures and Algorithms (1333203)/

Data Structure and Application (1333203) - Winter 2023 Solution

24 mins· ·
Study-Material Solutions Data-Structure 1333203 2023 Winter
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Table of Contents

Question 1(a) [3 marks]
#

Define linked list. List different types of linked list.

Answer:

DefinitionTypes of Linked List
A linked list is a linear data structure where elements are stored in nodes, and each node points to the next node in the sequence1. Singly Linked List
2. Doubly Linked List
3. Circular Linked List
4. Circular Doubly Linked List

Diagram:

SDCioinurgbclluyyl::ar:[[[DPDaratetavaNDNeaextxtat]|]Nex[t[D]Daattaa|[|NPNerexextvt]|]Dat[a[D|DaNatetaxa|t|N]Neexxtt][]PreNvU|LDLata|Next]NULL

Mnemonic: “Single, Double, Circle, Double-Circle”

Question 1(b) [4 marks]
#

Explain Linear and Non Linear Data structure in Python with examples.

Answer:

Data StructureDescriptionPython Examples
LinearElements arranged in sequential order where each element has exactly one predecessor and successor (except first and last)Lists: [1, 2, 3]
Tuples: (1, 2, 3)
Strings: "abc"
Queue: queue.Queue()
Non-LinearElements not arranged sequentially; an element can connect to multiple elementsDictionary: {"a": 1, "b": 2}
Set: {1, 2, 3}
Tree: Custom implementation
Graph: Custom implementation

Diagram:

graph TD
    A[Data Structures]
    A --> B[Linear]
    A --> C[Non-Linear]
    B --> D[Arrays]
    B --> E[Linked Lists]
    B --> F[Stacks]
    B --> G[Queues]
    C --> H[Trees]
    C --> I[Graphs]
    C --> J[Hash Tables]

Mnemonic: “Linear Listens In Sequence, Non-linear Navigates Various Paths”

Question 1(c) [7 marks]
#

Explain class, attributes, object and class method in python with suitable example.

Answer:

Diagram:

classDiagram
    class Student {
        -roll_no
        -name
        +__init__()
        +display()
    }

TermDescription
ClassBlueprint for creating objects with shared attributes and methods
AttributesVariables that store data inside a class
ObjectInstance of a class with specific attribute values
Class MethodFunctions defined within a class that can access and modify class states

Code:

class Student:
    # Class attribute
    school = "GTU"
    
    # Constructor
    def __init__(self, roll_no, name):
        # Instance attributes
        self.roll_no = roll_no
        self.name = name
    
    # Instance method
    def display(self):
        print(f"Roll No: {self.roll_no}, Name: {self.name}")
    
    # Class method
    @classmethod
    def change_school(cls, new_school):
        cls.school = new_school

# Creating object
student1 = Student(101, "Raj")
student1.display()  # Output: Roll No: 101, Name: Raj

Mnemonic: “Class Creates, Attributes Store, Objects Use, Methods Operate”

Question 1(c) OR [7 marks]
#

Define Data Encapsulation & Polymorphism. Develop a Python code to explain Polymorphism.

Answer:

ConceptDefinition
Data EncapsulationBundling data and methods into a single unit (class) and restricting direct access to some components
PolymorphismAbility of different classes to provide their own implementation of methods with the same name

Diagram:

graph TD
    A[Polymorphism]
    A --> B[Method Overriding]
    A --> C[Method Overloading]
    A --> D[Duck Typing]

Code:

# Polymorphism example
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Duck(Animal):
    def speak(self):
        return "Quack!"

# Function demonstrating polymorphism
def animal_sound(animal):
    return animal.speak()

# Creating objects
dog = Dog()
cat = Cat()
duck = Duck()

# Same function works for different animal objects
print(animal_sound(dog))   # Output: Woof!
print(animal_sound(cat))   # Output: Meow!
print(animal_sound(duck))  # Output: Quack!

Mnemonic: “Encapsulate to Protect, Polymorphism for Flexibility”

Question 2(a) [3 marks]
#

Differentiate between Stack and Queue.

Answer:

FeatureStackQueue
PrincipleLIFO (Last In First Out)FIFO (First In First Out)
OperationsPush, PopEnqueue, Dequeue
AccessElements can only be added/removed from one end (top)Elements are added at rear end and removed from front end

Diagram:

Stack:[[[321]]]Queue:[F1r]ont[2]R[e3a]r

Mnemonic: “Stack Piles Up, Queue Lines Up”

Question 2(b) [4 marks]
#

Write an algorithm for PUSH and POP operation of stack in python.

Answer:

PUSH Algorithm:

SEtna123dr...tCIAhfdedcnkoetlieffmueslntlta,cakitnicpsroesfmiuetlniltonto'ptobpy'1

POP Algorithm:

SEtna1234dr....tCIDRhfeeectcnrukoertmniefenrmtespttttrayoic,pekvrbeieydstr1eeilmeepvmteeynetlementat'top'

Code:

class Stack:
    def __init__(self, size):
        self.stack = []
        self.size = size
        self.top = -1
    
    def push(self, element):
        if self.top >= self.size - 1:
            return "Stack Overflow"
        else:
            self.top += 1
            self.stack.append(element)
            return "Pushed " + str(element)
    
    def pop(self):
        if self.top < 0:
            return "Stack Underflow"
        else:
            element = self.stack.pop()
            self.top -= 1
            return element

Mnemonic: “Push to Top, Pop from Top”

Question 2(c) [7 marks]
#

Convert following equation from infix to postfix using Stack. A * (B + C) - D / (E + F)

Answer:

Diagram:

IPnofsitxf:ix:AAB(CB++C)D-EDF/+(E+F)
StepSymbolStackOutput
1AA
2**A
3(* (A
4B* (A B
5+* ( +A B
6C* ( +A B C
7)*A B C +
8--A B C + *
9D-A B C + * D
10/- /A B C + * D
11(- / (A B C + * D
12E- / (A B C + * D E
13+- / ( +A B C + * D E
14F- / ( +A B C + * D E F
15)- /A B C + * D E F +
16endA B C + * D E F + / -

Answer: A B C + * D E F + / -

Mnemonic: “Operators Stack, Operands Print”

Question 2(a) OR [3 marks]
#

Differentiate between simple Queue and circular Queue.

Answer:

FeatureSimple QueueCircular Queue
StructureLinear data structureLinear data structure with connected ends
MemoryInefficient memory usage due to unused space after dequeueEfficient memory usage by reusing empty spaces
ImplementationFront always at index 0, rear increasesFront and rear move in circular fashion using modulo

Diagram:

graph LR
    A[Simple Queue] --> B[Front]
    B --> C[...]
    C --> D[Rear]

    E[Circular Queue] --> F[Front]
    F --> G[...]
    G --> H[Rear]
    H --> F

Mnemonic: “Simple Wastes, Circular Reuses”

Question 2(b) OR [4 marks]
#

Explain concept of recursive function with suitable example.

Answer:

Key AspectsDescription
DefinitionA function that calls itself to solve a smaller instance of the same problem
Base CaseThe condition where the function stops calling itself
Recursive CaseThe condition where the function calls itself with a simpler version of the problem

Diagram:

graph TD
    A[factorial(3)] --> B[3 * factorial(2)]
    B --> C[3 * 2 * factorial(1)]
    C --> D[3 * 2 * 1 * factorial(0)]
    D --> E[3 * 2 * 1 * 1]
    E --> F[3 * 2 * 1]
    F --> G[3 * 2]
    G --> H[6]

Code:

def factorial(n):
    # Base case
    if n == 0:
        return 1
    # Recursive case
    else:
        return n * factorial(n-1)

# Example
result = factorial(5)  # 5! = 120

Mnemonic: “Base Breaks, Recursion Returns”

Question 2(c) OR [7 marks]
#

Develop a python code to implement Enqueue and Dequeue operation in Queue.

Answer:

Diagram:

EDneq[q[u1u1e]e]u[u[e2e2:]:][[33]][4][1][[22]][[33]][[44]]

Code:

class Queue:
    def __init__(self, size):
        self.queue = []
        self.size = size
        self.front = 0
        self.rear = -1
        self.count = 0
    
    def enqueue(self, item):
        if self.count >= self.size:
            return "Queue is full"
        else:
            self.rear += 1
            self.queue.append(item)
            self.count += 1
            return "Enqueued " + str(item)
    
    def dequeue(self):
        if self.count <= 0:
            return "Queue is empty"
        else:
            item = self.queue.pop(0)
            self.count -= 1
            return item
    
    def display(self):
        return self.queue

# Test
q = Queue(5)
q.enqueue(10)
q.enqueue(20)
q.enqueue(30)
print(q.display())  # [10, 20, 30]
print(q.dequeue())  # 10
print(q.display())  # [20, 30]

Mnemonic: “Enqueue at End, Dequeue from Start”

Question 3(a) [3 marks]
#

Give Difference between Singly linked list and Circular linked list.

Answer:

FeatureSingly Linked ListCircular Linked List
Last NodePoints to NULLPoints back to the first node
TraversalHas a definite endCan be traversed continuously
MemoryEach node needs one pointerEach node needs one pointer

Diagram:

SCiinrgcluyl:ar:[[11]][[22]][[33]]NULL

Mnemonic: “Singly Stops, Circular Cycles”

Question 3(b) [4 marks]
#

Explain concept of Doubly linked list.

Answer:

Diagram:

NULL[Prev|1|Next][Prev|2|Next][Prev|3|Next]NULL
FeatureDescription
Node StructureEach node contains data and two pointers (previous and next)
NavigationCan traverse in both forward and backward directions
OperationsInsertion and deletion can be performed from both ends
Memory UsageRequires more memory than singly linked list due to extra pointer

Code:

class Node:
    def __init__(self, data):
        self.data = data
        self.prev = None
        self.next = None

Mnemonic: “Double Pointers, Double Directions”

Question 3(c) [7 marks]
#

Write an algorithm for following operation on singly linked list: 1. To insert a node at the beginning of the list. 2. To insert the node at the end of the list.

Answer:

Insert at Beginning:

graph LR
    A[Start] --> B[Create new node]
    B --> C[Set new node's data]
    C --> D[Set new node's next to head]
    D --> E[Set head to new node]
    E --> F[End]

Insert at End:

graph LR
    A[Start] --> B[Create new node]
    B --> C[Set new node's data]
    C --> D[Set new node's next to NULL]
    D --> E{Is head NULL?}
    E -->|Yes| F[Set head to new node]
    E -->|No| G[Traverse to last node]
    G --> H[Set last node's next to new node]
    F --> I[End]
    H --> I

Code:

def insert_at_beginning(head, data):
    new_node = Node(data)
    new_node.next = head
    return new_node  # New head

def insert_at_end(head, data):
    new_node = Node(data)
    new_node.next = None
    
    # If linked list is empty
    if head is None:
        return new_node
    
    # Traverse to the last node
    temp = head
    while temp.next:
        temp = temp.next
    
    # Link the last node to new node
    temp.next = new_node
    return head

Mnemonic: “Begin: New Leads Old, End: Old Leads New”

Question 3(a) OR [3 marks]
#

List different operations performed on singly linked list.

Answer:

Operations on Singly Linked List
1. Insertion (at beginning, middle, end)
2. Deletion (from beginning, middle, end)
3. Traversal (visiting each node)
4. Searching (finding a specific node)
5. Updating (modifying node data)

Diagram:

graph TD
    A[Linked List Operations]
    A --> B[Insertion]
    A --> C[Deletion]
    A --> D[Traversal]
    A --> E[Searching]
    A --> F[Updating]

Mnemonic: “Insert Delete Traverse Search Update”

Question 3(b) OR [4 marks]
#

Explain concept of Circular linked list.

Answer:

Diagram:

[1]--[-2-]----[-3-]-[4]
FeatureDescription
StructureLast node points to the first node instead of NULL
AdvantageAllows continuous traversal through all nodes
ApplicationsRound robin scheduling, circular buffer implementation
OperationsInsertion and deletion similar to singly linked list with special handling for the last node

Code:

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# Creating a circular linked list with 3 nodes
head = Node(1)
node2 = Node(2)
node3 = Node(3)

head.next = node2
node2.next = node3
node3.next = head  # Makes it circular

Mnemonic: “Last Links to First”

Question 3(c) OR [7 marks]
#

List application of linked list. Write an algorithm to count the number of nodes in singly linked list.

Answer:

Applications of Linked List
1. Implementation of stacks and queues
2. Dynamic memory allocation
3. Undo functionality in applications
4. Hash tables (chaining)
5. Adjacency lists for graphs

Algorithm to Count Nodes:

graph TD
    A[Start] --> B[Initialize count = 0]
    B --> C[Initialize temp = head]
    C --> D{temp != NULL?}
    D -->|Yes| E[increment count]
    D -->|No| F[Return count]
    E --> G[temp = temp.next]
    G --> D

Code:

def count_nodes(head):
    count = 0
    temp = head
    
    while temp:
        count += 1
        temp = temp.next
    
    return count

# Example usage
# Assuming head points to the first node of a linked list
total_nodes = count_nodes(head)
print(f"Total nodes: {total_nodes}")

Mnemonic: “Count While Moving”

Question 4(a) [3 marks]
#

Compare Linear search with Binary search.

Answer:

FeatureLinear SearchBinary Search
Data ArrangementWorks on both sorted and unsorted dataWorks only on sorted data
Time ComplexityO(n)O(log n)
ImplementationSimplerMore complex
Best ForSmall datasets or unsorted dataLarge sorted datasets

Diagram:

LBiinneaarry::[S[L1e1o]q]wue[e[r2n2]t]hia[a[Cl3l3hf]]ecc[h[k4e4]c]mUkip[i[dp5n5de]g]lre[[h66a]]lf[[77]][[88]]

Mnemonic: “Linear Looks at All, Binary Breaks in Half”

Question 4(b) [4 marks]
#

Write an algorithm for selection sort method.

Answer:

Diagram:

IPPPPnaaaaisssstssssia1234l:::::[[[[[51111,,,,,33222,,,,,88833,,,,,15555,,,,,22388]]]]]((((FFFFiiiinnnnddddmmmmiiiinnnn====1235,,,,sssawwwlaaarpppeawwwdiiiyttthhhin538)))place)

Algorithm:

graph TD
    A[Start] --> B[For i = 0 to n-1]
    B --> C[Find minimum element in unsorted portion]
    C --> D[Swap minimum with first element of unsorted portion]
    D --> E[End]

Code Outline:

def selection_sort(arr):
    n = len(arr)
    
    for i in range(n):
        min_idx = i
        
        # Find the minimum element in unsorted array
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        
        # Swap the found minimum element with the first element
        arr[i], arr[min_idx] = arr[min_idx], arr[i]

Mnemonic: “Find Minimum, Swap Position”

Question 4(c) [7 marks]
#

Develop a python code to sort following list in ascending order using Bubble sort method. list1=[5,4,3,2,1,0]

Answer:

Diagram:

IPPPPPnaaaaaissssstsssssia12345l::::::[[[[[[543210,,,,,,432101,,,,,,321022,,,,,,210333,,,,,,104444,,,,,,055555]]]]]]

Code:

def bubble_sort(arr):
    n = len(arr)
    
    # Traverse through all array elements
    for i in range(n):
        # Last i elements are already in place
        for j in range(0, n-i-1):
            # Swap if current element is greater than next element
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    
    return arr

# Input list
list1 = [5, 4, 3, 2, 1, 0]

# Sorting the list
sorted_list = bubble_sort(list1)

# Displaying the result
print("Sorted list:", sorted_list)
# Output: Sorted list: [0, 1, 2, 3, 4, 5]

Mnemonic: “Bubble Biggest Upward”

Question 4(a) OR [3 marks]
#

Define sorting. List different sorting methods.

Answer:

DefinitionSorting Methods
Sorting is the process of arranging data in a specified order (ascending or descending)1. Bubble Sort
2. Selection Sort
3. Insertion Sort
4. Merge Sort
5. Quick Sort
6. Heap Sort
7. Radix Sort

Diagram:

graph TD
    A[Sorting Algorithms]
    A --> B[Comparison-based]
    A --> C[Non-comparison]
    B --> D[Bubble Sort]
    B --> E[Selection Sort]
    B --> F[Insertion Sort]
    B --> G[Merge Sort]
    B --> H[Quick Sort]
    C --> I[Counting Sort]
    C --> J[Radix Sort]
    C --> K[Bucket Sort]

Mnemonic: “Better Sort Improves Many Query Results”

Question 4(b) OR [4 marks]
#

Write an algorithm for Insertion sort method.

Answer:

Diagram:

IPPPPPnaaaaaissssstsssssia12345l::::::[[[[[[522211,,,,,,254422,,,,,,445543,,,,,,666654,,,,,,111165,,,,,,333336]]]]]](((((II6IInnnnssisseeseerrrrttattl24r13ebbaaaeedtfffytooberriereengi255pn)))lnaicneg))

Algorithm:

graph TD
    A[Start] --> B[For i = 1 to n-1]
    B --> C[Set key = arr[i]]
    C --> D[Set j = i-1]
    D --> E{j >= 0 and arr[j] > key?}
    E -->|Yes| F[Move element right]
    F --> G[Decrement j]
    G --> E
    E -->|No| H[Place key at correct position]
    H --> I[End]

Code Outline:

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        
        # Move elements that are greater than key
        # to one position ahead of their current position
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]
            j -= 1
        
        arr[j + 1] = key

Mnemonic: “Take Card, Insert In Order”

Question 4(c) OR [7 marks]
#

Develop a python code to sort following list in ascending order using selection sort method. list1=[6,3,25,8,-1,55,0]

Answer:

Diagram:

IPPPPPPnaaaaaaisssssstssssssia123456l:::::::[[[[[[[6------,111111,,,,,,3,300000,,,,,,25223333,55,,,,,,88666,88,,,,,,-6888166,,,,,,,55525555555555,,,,,,,22250035555]]]]]]]((((((FFFFFFiiiiiinnnnnnddddddmmmmmmiiiiiinnnnnn======-036821,,,,5,,sssaswwwlswaaarwapppeapapwwwdwiiiywitttithhhithnh3286)5)p5))l5a)ce)

Code:

def selection_sort(arr):
    n = len(arr)
    
    for i in range(n):
        # Find the minimum element in remaining unsorted array
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
                
        # Swap the found minimum element with the first element
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    
    return arr

# Input list
list1 = [6, 3, 25, 8, -1, 55, 0]

# Sorting the list
sorted_list = selection_sort(list1)

# Displaying the result
print("Sorted list:", sorted_list)
# Output: Sorted list: [-1, 0, 3, 6, 8, 25, 55]

Mnemonic: “Select Smallest, Shift to Start”

Question 5(a) [3 marks]
#

Define following terms regarding Tree data structure: 1. Forest 2. Root node 3. Leaf node

Answer:

TermDefinition
ForestCollection of disjoint trees (multiple trees without connections between them)
Root NodeTopmost node of a tree with no parent, from which all other nodes are descended
Leaf NodeNode with no children (terminal node at the bottom of the tree)

Diagram:

FRLooeroaetfs::t:[A][TRr]e[eB1][TLNr]oeec2h[iLl]drTernee3

Mnemonic: “Forest has Many Roots, Roots Lead All, Leaves End All”

Question 5(b) [4 marks]
#

Draw Binary search tree for 78,58,82,15,66,80,99 and write In-order traversal for the tree.

Answer:

Binary Search Tree:

15586678808299

In-order Traversal:

StepVisit Order
1Visit left subtree of 78
2Visit left subtree of 58
3Visit 15
4Visit 58
5Visit 66
6Visit 78
7Visit left subtree of 82
8Visit 80
9Visit 82
10Visit 99

In-order Traversal Result: 15, 58, 66, 78, 80, 82, 99

Mnemonic: “Left, Root, Right”

Question 5(c) [7 marks]
#

Write an algorithm for following operation: 1. Insertion of Node in Binary Tree 2. Deletion of Node in Binary Tree

Answer:

Insertion Algorithm:

graph TD
    A[Start] --> B[Create new node with given data]
    B --> C{Is root NULL?}
    C -->|Yes| D[Set root to new node]
    C -->|No| E[Find position using level order traversal]
    E --> F[Insert node at first vacant position]
    D --> G[End]
    F --> G

Deletion Algorithm:

graph TD
    A[Start] --> B{Is tree empty?}
    B -->|Yes| C[Return]
    B -->|No| D[Find node to delete]
    D --> E[Find deepest rightmost node]
    E --> F[Replace node to delete with deepest rightmost node]
    F --> G[Delete deepest rightmost node]
    C --> H[End]
    G --> H

Code:

class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

# Insertion in Binary Tree
def insert(root, data):
    if root is None:
        return Node(data)
    
    # Level order traversal to find vacant position
    queue = []
    queue.append(root)
    
    while queue:
        temp = queue.pop(0)
        
        if temp.left is None:
            temp.left = Node(data)
            break
        else:
            queue.append(temp.left)
            
        if temp.right is None:
            temp.right = Node(data)
            break
        else:
            queue.append(temp.right)
    
    return root

# Deletion in Binary Tree
def delete_node(root, key):
    if root is None:
        return None
    
    if root.left is None and root.right is None:
        if root.data == key:
            return None
        else:
            return root
    
    # Find the node to delete
    key_node = None
    # Find the deepest node
    last = None
    parent = None
    
    # Level order traversal
    queue = []
    queue.append(root)
    
    while queue:
        temp = queue.pop(0)
        
        if temp.data == key:
            key_node = temp
            
        if temp.left:
            parent = temp
            queue.append(temp.left)
            last = temp.left
            
        if temp.right:
            parent = temp
            queue.append(temp.right)
            last = temp.right
    
    if key_node:
        # Replace with deepest node's data
        key_node.data = last.data
        
        # Delete the deepest node
        if parent.right == last:
            parent.right = None
        else:
            parent.left = None
    
    return root

Mnemonic: “Insert at Empty, Delete by Swap and Remove”

Question 5(a) OR [3 marks]
#

Define following terms regarding Tree data structure: 1. In-degree 2. Out-degree 3. Depth

Answer:

TermDefinition
In-degreeNumber of edges coming into a node (always 1 for each node except root node in a tree)
Out-degreeNumber of edges going out from a node (number of children)
DepthLength of the path from root to the node (number of edges in path)

Diagram:

DBEA(RCoo(FtD,e(pDDteehpptt1hh)20))
NodeIn-degreeOut-degree
A02
B12
C11
D10
E10
F10

Mnemonic: “In Counts Parents, Out Counts Children, Depth Counts Edges from Root”

Question 5(b) OR [4 marks]
#

Write Preorder and postorder traversal of following Binary tree.

Binary Tree:

102031000125000300

Answer:

TraversalOrderResult
PreorderRoot, Left, Right100, 20, 10, 30, 200, 150, 300
PostorderLeft, Right, Root10, 30, 20, 150, 300, 200, 100

Preorder Visualization:

graph TD
    A[100] --> B[Visit 100]
    B --> C[Visit left subtree]
    C --> D[Visit 20]
    D --> E[Visit 10]
    E --> F[Visit 30]
    F --> G[Visit right subtree]
    G --> H[Visit 200]
    H --> I[Visit 150]
    I --> J[Visit 300]

Postorder Visualization:

graph TD
    A[100] --> B[Visit left subtree]
    B --> C[Visit 10]
    C --> D[Visit 30]
    D --> E[Visit 20]
    E --> F[Visit right subtree]
    F --> G[Visit 150]
    G --> H[Visit 300]
    H --> I[Visit 200]
    I --> J[Visit 100]

Mnemonic:

  • Preorder: “Root First, Then Children”
  • Postorder: “Children First, Then Root”

Question 5(c) OR [7 marks]
#

Develop a program to implement construction of Binary Search Tree.

Answer:

Diagram:

graph TD
    A[Root] -->|Insert 50| B[50]
    B -->|Insert 30| C[50]
    C -.-> D[30]
    C -->|Insert 70| E[50]
    E -.-> F[30]
    E --> G[70]
    G -->|Insert 20| H[50]
    H -.-> I[30]
    I -.-> J[20]
    H --> K[70]

Code:

class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None

def insert(root, key):
    # If the tree is empty, return a new node
    if root is None:
        return Node(key)
    
    # Otherwise, recur down the tree
    if key < root.key:
        root.left = insert(root.left, key)
    else:
        root.right = insert(root.right, key)
    
    # Return the unchanged node pointer
    return root

def inorder(root):
    if root:
        inorder(root.left)
        print(root.key, end=" ")
        inorder(root.right)

def preorder(root):
    if root:
        print(root.key, end=" ")
        preorder(root.left)
        preorder(root.right)

def postorder(root):
    if root:
        postorder(root.left)
        postorder(root.right)
        print(root.key, end=" ")

# Driver program to test the above functions
def main():
    # Create BST with these elements: 50, 30, 20, 40, 70, 60, 80
    root = None
    elements = [50, 30, 20, 40, 70, 60, 80]
    
    for element in elements:
        root = insert(root, element)
    
    # Print traversals
    print("Inorder traversal: ", end="")
    inorder(root)
    print("\nPreorder traversal: ", end="")
    preorder(root)
    print("\nPostorder traversal: ", end="")
    postorder(root)

# Run the program
main()

Example Output:

Inorder traversal: 20 30 40 50 60 70 80
Preorder traversal: 50 30 20 40 70 60 80
Postorder traversal: 20 40 30 60 80 70 50

Mnemonic: “Insert Smaller Left, Larger Right”

Related

Elements of Electrical & Electronics Engineering (1313202) - Winter 2023 Solution
15 mins
Study-Material Solutions Electrical Electronics 1313202 2023 Winter
Communication Engineering (1333201) - Winter 2023 Solution
24 mins
Study-Material Solutions Communication-Engineering 1333201 2023 Winter
Microprocessor and Microcontroller (4341101) - Winter 2023 Solution
19 mins
Study-Material Solutions Microprocessor 4341101 2023 Winter
Electronic Circuits & Applications (4321103) - Winter 2023 Solution
16 mins
Study-Material Solutions Electronics 4321103 2023 Winter
Principles of Electronic Communication (4331104) - Winter 2023 Solution
20 mins
Study-Material Solutions Electronic-Communication 4331104 2023 Winter
Fundamentals of Electrical Engineering (4311101) - Winter 2023 Solution
12 mins
Study-Material Solutions Electrical-Engineering 4311101 2023 Winter