<s>[INST] class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class Stack:
    def __init__(self):
        self.top = None

    def push(self, data):
        newNode = Node(data)
        if self.top is None:
            self.top = newNode
        else:
            newNode.next = self.top
            self.top = newNode

    def pop(self):
        if self.top is None:
            return None
        else:
            popped_node = self.top
            self.top = self.top.next
            popped_node.next = None
            return popped_node.data

    def peek(self):
        return self.top.data if self.top else None

    def is_empty(self):
        return self.top is None

    def size(self):
        temp = self.top
        count = 0
        while temp:
            count += 1
            temp = temp.next
        return count

    def max_size(self):
        return self.size()

class Queue:
    def __init__(self):
        self.head = None
        self.tail = None

    def enqueue(self, item):
        new_node = Node(item)
        if self.tail is None:
            self.head = new_node
        else:
            self.tail.next = new_node
        self.tail = new_node

    def dequeue(self):
        if self.head is None:
            return None
        else:
            dequeued_node = self.head
            self.head = self.head.next
            if self.head is None:
                self.tail = None
            return dequeued_node.data

    def peek(self):
        return self.head.data if self.head else None

    def is_empty(self):
        return self.head is None

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

    def max_size(self):
        return self.size()

class Graph:
    def __init__(self):
        self.adjacencyList = {}

    def addNode(self, node):
        if node not in self.adjacencyList:
            self.adjacencyList[node] = []

    def addEdge(self, node1, node2):
        if node1 in self.adjacencyList and node2 in self.adjacencyList:
            self.adjacencyList[node1].append(node2)

    def printGraph(self):
        for key, value in self.adjacencyList.items():
            print(key, "->", value)

    def DFS(self, startNode):
        visited = set()
        traversalOrder = []
        self._DFS_helper(startNode, visited, traversalOrder)
        return traversalOrder

    def _DFS_helper(self, node, visited, traversalOrder):
        visited.add(node)
        traversalOrder.append(node)
        if node in self.adjacencyList:
            for neighbor in self.adjacencyList[node]:
                if neighbor not in visited:
                    self._DFS_helper(neighbor, visited, traversalOrder)

    def BFS(self, startNode):
        visited = set()
        traversalOrder = []
        queue = Queue()
        queue.enqueue(startNode)
        visited.add(startNode)
        while queue.size() > 0:
            currentNode = queue.dequeue()
            traversalOrder.append(currentNode)
            if currentNode in self.adjacencyList:
                for neighbor in self.adjacencyList[currentNode]:
                    if neighbor not in visited:
                        visited.add(neighbor)
                        queue.enqueue(neighbor)
        return traversalOrder

    def topologicalSort(self):
        visited = set()
        stack = Stack()
        for node in self.adjacencyList:
            if node not in visited:
                self._topologicalSort_helper(node, visited, stack)
        return stack

    def _topologicalSort_helper(self, node, visited, stack):
        visited.add(node)
        if node in self.adjacencyList:
            for neighbor in self.adjacencyList[node]:
                if neighbor not in visited:
                    self._topologicalSort_helper(neighbor, visited, stack)
        stack.push(node)[/INST]