diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..8ed7694
Binary files /dev/null and b/.DS_Store differ
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8c470af..f5acf43 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -67,7 +67,7 @@ You can contribute by:
- Create `.py` file for a particular algorithm or code
- > If data structure folder already exists inside subfolder, kindly add your code in the respective folder
+ > If data structure folder already exists in the repo, kindly add your code in the respective folder.
6. Add all the changes that you have made
diff --git a/Clustering Techniques/Affinity_Propagation_Clustering_Algorithm.py b/Clustering Techniques/Affinity_Propagation_Clustering_Algorithm.py
new file mode 100644
index 0000000..f111ff9
--- /dev/null
+++ b/Clustering Techniques/Affinity_Propagation_Clustering_Algorithm.py
@@ -0,0 +1,37 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import AffinityPropagation
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+model = AffinityPropagation(damping=0.7)
+
+# train the model
+model.fit(training_data)
+
+# assign each data point to a cluster
+result = model.predict(training_data)
+
+# get all of the unique clusters
+clusters = unique(result)
+
+# plot the clusters
+for cluster in clusters:
+ # get data points that fall in this cluster
+ index = where(result == cluster)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the plot
+pyplot.show()
diff --git a/Clustering Techniques/Agglomerative_Clustering_Algorithm.py b/Clustering Techniques/Agglomerative_Clustering_Algorithm.py
new file mode 100644
index 0000000..9786ab7
--- /dev/null
+++ b/Clustering Techniques/Agglomerative_Clustering_Algorithm.py
@@ -0,0 +1,34 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import AgglomerativeClustering
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+agglomerative_model = AgglomerativeClustering(n_clusters=2)
+
+# assign each data point to a cluster
+agglomerative_result = agglomerative_model.fit_predict(training_data)
+
+# get all of the unique clusters
+agglomerative_clusters = unique(agglomerative_result)
+
+# plot the clusters
+for agglomerative_cluster in agglomerative_clusters:
+ # get data points that fall in this cluster
+ index = where(agglomerative_result == agglomerative_clusters)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the Agglomerative Hierarchy plot
+pyplot.show()
diff --git a/Clustering Techniques/Birch_Algorithm.py b/Clustering Techniques/Birch_Algorithm.py
new file mode 100644
index 0000000..c209678
--- /dev/null
+++ b/Clustering Techniques/Birch_Algorithm.py
@@ -0,0 +1,37 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import Birch
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+birch_model = Birch(threshold=0.03, n_clusters=2)
+
+# train the model
+birch_model.fit(training_data)
+
+# assign each data point to a cluster
+birch_result = birch_model.predict(training_data)
+
+# get all of the unique clusters
+birch_clusters = unique(birch_result)
+
+# plot the BIRCH clusters
+for birch_cluster in birch_clusters:
+ # get data points that fall in this cluster
+ index = where(birch_result == birch_clusters)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the BIRCH plot
+pyplot.show()
diff --git a/Clustering Techniques/DBScan_Model.py b/Clustering Techniques/DBScan_Model.py
new file mode 100644
index 0000000..06b9af2
--- /dev/null
+++ b/Clustering Techniques/DBScan_Model.py
@@ -0,0 +1,37 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import DBSCAN
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+dbscan_model = DBSCAN(eps=0.25, min_samples=9)
+
+# train the model
+dbscan_model.fit(training_data)
+
+# assign each data point to a cluster
+dbscan_result = dbscan_model.predict(training_data)
+
+# get all of the unique clusters
+dbscan_cluster = unique(dbscan_result)
+
+# plot the DBSCAN clusters
+for dbscan_cluster in dbscan_clusters:
+ # get data points that fall in this cluster
+ index = where(dbscan_result == dbscan_clusters)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the DBSCAN plot
+pyplot.show()
diff --git a/Clustering Techniques/Gaussain_Mixture_Model.py b/Clustering Techniques/Gaussain_Mixture_Model.py
new file mode 100644
index 0000000..edfcd26
--- /dev/null
+++ b/Clustering Techniques/Gaussain_Mixture_Model.py
@@ -0,0 +1,37 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.mixture import GaussianMixture
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+gaussian_model = GaussianMixture(n_components=2)
+
+# train the model
+gaussian_model.fit(training_data)
+
+# assign each data point to a cluster
+gaussian_result = gaussian_model.predict(training_data)
+
+# get all of the unique clusters
+gaussian_clusters = unique(gaussian_result)
+
+# plot Gaussian Mixture the clusters
+for gaussian_cluster in gaussian_clusters:
+ # get data points that fall in this cluster
+ index = where(gaussian_result == gaussian_clusters)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the Gaussian Mixture plot
+pyplot.show()
diff --git a/Clustering Techniques/Mean_Shift_Clustering_Algorithm.py b/Clustering Techniques/Mean_Shift_Clustering_Algorithm.py
new file mode 100644
index 0000000..230c67b
--- /dev/null
+++ b/Clustering Techniques/Mean_Shift_Clustering_Algorithm.py
@@ -0,0 +1,34 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import MeanShift
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+mean_model = MeanShift()
+
+# assign each data point to a cluster
+mean_result = mean_model.fit_predict(training_data)
+
+# get all of the unique clusters
+mean_clusters = unique(mean_result)
+
+# plot Mean-Shift the clusters
+for mean_cluster in mean_clusters:
+ # get data points that fall in this cluster
+ index = where(mean_result == mean_cluster)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the Mean-Shift plot
+pyplot.show()
diff --git a/Clustering Techniques/Optics_Algorithm.py b/Clustering Techniques/Optics_Algorithm.py
new file mode 100644
index 0000000..c198fa3
--- /dev/null
+++ b/Clustering Techniques/Optics_Algorithm.py
@@ -0,0 +1,34 @@
+from numpy import unique
+from numpy import where
+from matplotlib import pyplot
+from sklearn.datasets import make_classification
+from sklearn.cluster import OPTICS
+
+# initialize the data set we'll work with
+training_data, _ = make_classification(
+ n_samples=1000,
+ n_features=2,
+ n_informative=2,
+ n_redundant=0,
+ n_clusters_per_class=1,
+ random_state=4
+)
+
+# define the model
+optics_model = OPTICS(eps=0.75, min_samples=10)
+
+# assign each data point to a cluster
+optics_result = optics_model.fit_predict(training_data)
+
+# get all of the unique clusters
+optics_clusters = unique(optics_clusters)
+
+# plot OPTICS the clusters
+for optics_cluster in optics_clusters:
+ # get data points that fall in this cluster
+ index = where(optics_result == optics_clusters)
+ # make the plot
+ pyplot.scatter(training_data[index, 0], training_data[index, 1])
+
+# show the OPTICS plot
+pyplot.show()
diff --git a/Clustering Techniques/kmeans.py b/Clustering Techniques/kmeans.py
new file mode 100644
index 0000000..06a6911
--- /dev/null
+++ b/Clustering Techniques/kmeans.py
@@ -0,0 +1,79 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+# Function to accept data from the user
+
+
+def get_user_data():
+ num_points = int(input("Enter the number of data points: "))
+ data = []
+ for i in range(num_points):
+ x = float(input(f"Enter x-coordinate for data point {i+1}: "))
+ y = float(input(f"Enter y-coordinate for data point {i+1}: "))
+ data.append([x, y])
+ return np.array(data)
+
+# Function to plot data points and centroids
+
+
+def plot(data, centroids, cluster):
+ plt.scatter(data[:, 0], data[:, 1], c=cluster)
+ plt.scatter(centroids[:, 0], centroids[:, 1], c='r')
+ plt.show()
+
+# Function to assign each data point to the closest centroid
+
+
+def assign_cluster(data, centroids):
+ cluster = []
+ # Looping through each data point
+ for i in range(len(data)):
+ distances = []
+ # Looping through each centroid
+ for j in range(len(centroids)):
+ # Calculating the distance between the data point and the centroid
+ distances.append(np.linalg.norm(data[i] - centroids[j]))
+ # Assigning the data point to the closest centroid
+ cluster.append(np.argmin(distances))
+ return cluster
+
+# Function to update centroids based on the assigned clusters
+
+
+def update_centroids(data, cluster, k):
+ centroids = []
+ # Looping through each cluster
+ for i in range(k):
+ # Calculating the new centroid
+ centroids.append(np.mean(data[np.array(cluster) == i], axis=0))
+ return np.array(centroids)
+
+
+# Get user input for data points
+data = get_user_data()
+
+# Plot the initial data points
+plt.scatter(data[:, 0], data[:, 1])
+
+# Get user input for the number of clusters (k)
+k = int(input("Enter the number of clusters (k): "))
+
+# Get user input for initial centroids
+centroids = []
+for i in range(k):
+ x = float(input(f"Enter initial x-coordinate for centroid {i+1}: "))
+ y = float(input(f"Enter initial y-coordinate for centroid {i+1}: "))
+ centroids.append([x, y])
+centroids = np.array(centroids)
+
+# Run the k-means algorithm for a specified number of iterations
+num_iterations = 10
+for i in range(num_iterations):
+ cluster = assign_cluster(data, centroids)
+ centroids = update_centroids(data, cluster, k)
+
+# Plot the final clusters and centroids
+plot(data, centroids, cluster)
+
+# Display the final clusters
+print("Final clusters:", cluster)
diff --git a/Codes/Sorting Techniques/Merge_Sort.py b/Codes/Sorting Techniques/Merge_Sort.py
deleted file mode 100644
index cad46f0..0000000
--- a/Codes/Sorting Techniques/Merge_Sort.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Untitled0.ipynb
-
-Automatically generated by Colaboratory.
-
-Original file is located at
- https://colab.research.google.com/drive/1r_ESNZfmsamM3vf802CW01GUvfLfgmjs
-
-# Merge Sort
-"""
-
-def merger(a,start,mid,end):
- temp=[]
- for i in range(len(a)):
- temp.append(0)
- i = start
- j = mid + 1
- ti = start
- while i <= mid and j <= end:
- if a[i] < a[j]:
- temp[ti] = a[i]
- ti+=1
- i+=1
- else:
- temp[ti] = a[j]
- ti+=1
- j+=1
- while i <= mid:
- temp[ti] = a[i]
- ti+=1
- i+=1
- while j <= end:
- temp[ti] = a[j]
- ti+=1
- j+=1
-
- for i in range(start,end+1):
- a[i] = temp[i]
-
-def mergesort(a,start,end):
- if start < end:
- mid = (start+end)//2
- mergesort(a,start,mid)
- mergesort(a,mid+1,end)
- merger(a,start,mid,end)
-
-
-a = []
-size = int(input('Enter size of array: '))
-print('')
-for i in range(size):
- data = int(input('Enter element: '))
- a.append(data)
-print('')
-print('Elements are: ',a)
-
-mergesort(a,0,len(a)-1)
-print('After sorting elements are: ',a)
\ No newline at end of file
diff --git a/Graphs/A_Star.py b/Graphs/A_Star.py
new file mode 100644
index 0000000..ae13169
--- /dev/null
+++ b/Graphs/A_Star.py
@@ -0,0 +1,139 @@
+from collections import defaultdict
+
+class Graph:
+ def __init(self):
+ self.graph = defaultdict(list)
+
+ def add_edge(self, u, v, cost=1):
+ self.graph[u].append((v, cost))
+
+ def bfs(self, start_node):
+ visited = [False] * (max(self.graph) + 1)
+ queue = []
+
+ queue.append(start_node)
+ visited[start_node] = True
+
+ while queue:
+ node = queue.pop(0)
+ print(node, end=" ")
+
+ for neighbor in self.graph[node]:
+ neighbor_node, _ = neighbor
+ if not visited[neighbor_node]:
+ queue.append(neighbor_node)
+ visited[neighbor_node] = True
+
+class Node():
+ def __init__(self, state, parent, action, heuristic, cost):
+ self.state = state
+ self.parent = parent
+ self.action = action
+ self.heuristic = heuristic
+ self.cost = cost
+ self.combined = heuristic + cost
+
+class StackFrontier():
+ def __init__(self):
+ self.frontier = []
+
+ def add(self, node):
+ self.frontier.append(node)
+
+ def contains_state(self, state):
+ return any(node.state == state for node in self.frontier)
+
+ def empty(self):
+ return len(self.frontier) == 0
+
+ def remove(self):
+ if self.empty():
+ raise Exception("Empty frontier")
+ else:
+ node = self.frontier.pop()
+ return node
+
+class QueueFrontier(StackFrontier):
+ def remove(self):
+ if self.empty():
+ raise Exception("Empty frontier")
+ else:
+ node = self.frontier.pop(0)
+ return node
+
+class gbfsFrontier(StackFrontier):
+ def remove(self):
+ if self.empty():
+ raise Exception("Empty Frontier")
+ else:
+ node = min(self.frontier, key=lambda x: x.heuristic)
+ self.frontier.remove(node)
+ return node
+
+class a_starFrontier(StackFrontier):
+ def remove(self):
+ if self.empty():
+ raise Exception("Empty Frontier")
+ else:
+ node = min(self.frontier, key=lambda x: x.combined)
+ self.frontier.remove(node)
+ return node
+
+class AStarGraph(Graph):
+ def a_star(self, start_node, goal_node):
+ visited = [False] * (max(self.graph) + 1)
+ frontier = a_starFrontier()
+ start_state = Node(start_node, None, None, self.manhattan(start_node, goal_node), 0)
+ frontier.add(start_state)
+
+ while not frontier.empty():
+ node = frontier.remove()
+ state = node.state
+
+ if state == goal_node:
+ path = []
+ while node.parent is not None:
+ path.append(node.state)
+ node = node.parent
+ path.append(start_node)
+ path.reverse()
+ return path
+
+ visited[state] = True
+
+ for neighbor, cost in self.graph[state]:
+ if not visited[neighbor]:
+ new_cost = node.cost + cost
+ heuristic = self.manhattan(neighbor, goal_node)
+ neighbor_state = Node(neighbor, node, None, heuristic, new_cost)
+ frontier.add(neighbor_state)
+
+ return None
+
+ def manhattan(self, node, goal_node):
+ x1, y1 = node % 3, node // 3
+ x2, y2 = goal_node % 3, goal_node // 3
+ return abs(x1 - x2) + abs(y1 - y2)
+
+# Example usage with user input:
+a_star_graph = AStarGraph()
+
+# Get user input for defining the graph
+while True:
+ u = int(input("Enter edge source node (or -1 to stop): "))
+ if u == -1:
+ break
+ v = int(input("Enter edge target node: "))
+ cost = int(input("Enter edge cost: "))
+ a_star_graph.add_edge(u, v, cost)
+
+# Get user input for the start and goal nodes
+start_node = int(input("Enter the start node: "))
+goal_node = int(input("Enter the goal node: "))
+
+print(f"A* search starting from node {start_node} to reach node {goal_node}:")
+path = a_star_graph.a_star(start_node, goal_node)
+if path:
+ print("Path:", path)
+else:
+ print("No path found")
diff --git a/Graphs/BellMan_Ford_Algorithm.py b/Graphs/BellMan_Ford_Algorithm.py
new file mode 100644
index 0000000..0d305e3
--- /dev/null
+++ b/Graphs/BellMan_Ford_Algorithm.py
@@ -0,0 +1,53 @@
+# The Bellman-Ford Algorithm is a single-source, shortest-path algorithm used to find the shortest paths from a source node to all other nodes in a weighted graph, even when the graph contains negative edge weights. It works by iteratively relaxing the edges in the graph, ensuring that it can detect and handle negative weight cycles.
+
+# Class to represent a graph
+
+class Graph:
+
+ def __init__(self, vertices):
+ self.V = vertices # No. of vertices
+ self.graph = []
+
+ # function to add an edge to graph
+ def addEdge(self, u, v, w):
+ self.graph.append([u, v, w])
+
+ # utility function used to print the solution
+ def printArr(self, dist):
+ print("Vertex Distance from Source")
+ for i in range(self.V):
+ print("{0}\t\t{1}".format(i, dist[i]))
+
+ # The main function that finds shortest distances from src to
+ # all other vertices using Bellman-Ford algorithm. The function
+ # also detects negative weight cycle
+ def BellmanFord(self, src):
+
+ # Step 1: Initialize distances from src to all other vertices
+ # as INFINITE
+ dist = [float("Inf")] * self.V
+ dist[src] = 0
+
+ # Step 2: Relax all edges |V| - 1 times. A simple shortest
+ # path from src to any other vertex can have at-most |V| - 1
+ # edges
+ for _ in range(self.V - 1):
+ # Update dist value and parent index of the adjacent vertices of
+ # the picked vertex. Consider only those vertices which are still in
+ # queue
+ for u, v, w in self.graph:
+ if dist[u] != float("Inf") and dist[u] + w < dist[v]:
+ dist[v] = dist[u] + w
+
+ # Step 3: check for negative-weight cycles. The above step
+ # guarantees shortest distances if graph doesn't contain
+ # negative weight cycle. If we get a shorter path, then there
+ # is a cycle.
+
+ for u, v, w in self.graph:
+ if dist[u] != float("Inf") and dist[u] + w < dist[v]:
+ print("Graph contains negative weight cycle")
+ return
+
+ # print all distance
+ self.printArr(dist)
\ No newline at end of file
diff --git a/Graphs/Breadth_First_Search (BFS).py b/Graphs/Breadth_First_Search (BFS).py
new file mode 100644
index 0000000..065d887
--- /dev/null
+++ b/Graphs/Breadth_First_Search (BFS).py
@@ -0,0 +1,49 @@
+# Initialize an empty graph
+graph = {}
+
+# Function to add an edge to the graph
+def add_edge(graph, u, v):
+ if u in graph:
+ graph[u].append(v)
+ else:
+ graph[u] = [v]
+
+# Function to print a BFS of a graph
+def bfs(graph, start_node):
+ if start_node not in graph:
+ print("Start node not found in the graph.")
+ return
+
+ # Mark vertices as False means not visited
+ visited = {node: False for node in graph}
+
+ # Make an empty queue for BFS
+ queue = []
+
+ # Mark the given start node as visited and add it to the queue
+ visited[start_node] = True
+ queue.append(start_node)
+
+ while queue:
+ # Remove the front vertex (or the vertex at the 0th index) from the queue and print it.
+ v = queue.pop(0)
+ print(v, end=" ")
+
+ # Get all adjacent nodes of the removed node v from the graph dictionary.
+ # If an adjacent node has not been visited yet, mark it as visited and add it to the queue.
+ for neigh in graph[v]:
+ if not visited[neigh]:
+ visited[neigh] = True
+ queue.append(neigh)
+
+# Input from the user to create the graph
+while True:
+ u = input("Enter the source node (or 'quit' to finish): ")
+ if u == 'quit':
+ break
+ v = input(f"Enter the destination node(s) for node {u} (comma-separated): ")
+ for dest in v.split(','):
+ add_edge(graph, u, dest)
+
+start_node = input("Enter the start node for BFS: ")
+bfs(graph, start_node)
diff --git a/Graphs/Depth_First_Search (DFS).py b/Graphs/Depth_First_Search (DFS).py
new file mode 100644
index 0000000..fb41911
--- /dev/null
+++ b/Graphs/Depth_First_Search (DFS).py
@@ -0,0 +1,24 @@
+def create_graph():
+ graph = {}
+ n = int(input("Enter the number of nodes: "))
+ for i in range(n):
+ node = str(i)
+ edges = set(input(f"Enter the edges for node {node} (space-separated): ").split())
+ graph[node] = edges
+ return graph
+
+def dfs(graph, start, visited=None):
+ if visited is None:
+ visited = set()
+ visited.add(start)
+
+ print(start)
+
+ for next_node in graph[start] - visited:
+ dfs(graph, next_node, visited)
+ return visited
+
+graph = create_graph()
+start_node = input("Enter the starting node: ")
+
+dfs(graph, start_node)
diff --git a/Graphs/Floyd_Warshall_Algorithm.py b/Graphs/Floyd_Warshall_Algorithm.py
new file mode 100644
index 0000000..1a65876
--- /dev/null
+++ b/Graphs/Floyd_Warshall_Algorithm.py
@@ -0,0 +1,78 @@
+# The Floyd-Warshall Algorithm is a dynamic programming algorithm used to find the shortest paths between all pairs of nodes in a weighted graph. It works for
+# directed or undirected graphs with positive or negative edge weights and is particularly valuable when you need to compute and store all shortest paths in
+# a graph. The algorithm has a time and space complexity of O(n ^ 3), making it
+# suitable for small to moderately sized graphs.
+
+
+# Number of vertices in the graph
+V = 4
+
+# Define infinity as the large
+# enough value. This value will be
+# used for vertices not connected to each other
+INF = 99999
+
+# Solves all pair shortest path
+# via Floyd Warshall Algorithm
+
+
+def floydWarshall(graph):
+ """ dist[][] will be the output
+ matrix that will finally
+ have the shortest distances
+ between every pair of vertices """
+ """ initializing the solution matrix
+ same as input graph matrix
+ OR we can say that the initial
+ values of shortest distances
+ are based on shortest paths considering no
+ intermediate vertices """
+
+ dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
+
+ """ Add all vertices one by one
+ to the set of intermediate
+ vertices.
+ ---> Before start of an iteration,
+ we have shortest distances
+ between all pairs of vertices
+ such that the shortest
+ distances consider only the
+ vertices in the set
+ {0, 1, 2, .. k-1} as intermediate vertices.
+ ----> After the end of a
+ iteration, vertex no. k is
+ added to the set of intermediate
+ vertices and the
+ set becomes {0, 1, 2, .. k}
+ """
+ for k in range(V):
+
+ # pick all vertices as source one by one
+ for i in range(V):
+
+ # Pick all vertices as destination for the
+ # above picked source
+ for j in range(V):
+
+ # If vertex k is on the shortest path from
+ # i to j, then update the value of dist[i][j]
+ dist[i][j] = min(dist[i][j],
+ dist[i][k] + dist[k][j]
+ )
+ printSolution(dist)
+
+# A utility function to print the solution
+
+
+def printSolution(dist):
+ print("Following matrix shows the shortest distances\
+between every pair of vertices")
+ for i in range(V):
+ for j in range(V):
+ if (dist[i][j] == INF):
+ print("%7s" % ("INF"), end=" ")
+ else:
+ print("%7d\t" % (dist[i][j]), end=' ')
+ if j == V-1:
+ print()
diff --git a/Graphs/Greedy_Best_First_Search (GBFS).py b/Graphs/Greedy_Best_First_Search (GBFS).py
new file mode 100644
index 0000000..f569fae
--- /dev/null
+++ b/Graphs/Greedy_Best_First_Search (GBFS).py
@@ -0,0 +1,113 @@
+import sys
+import numpy as np
+from collections import defaultdict
+
+class Node():
+ def __init__(self, state, parent, action, heuristic):
+ self.state = state
+ self.parent = parent
+ self.action = action
+ self.heuristic = heuristic
+
+class StackFrontier():
+ def __init__(self):
+ self.frontier = []
+
+ def add(self, node):
+ self.frontier.append(node)
+
+ def contains_state(self, state):
+ return any(node.state == state for node in self.frontier)
+
+ def empty(self):
+ return len(self.frontier) == 0
+
+ def remove(self):
+ if self.empty():
+ raise Exception("empty frontier")
+ else:
+ node = self.frontier[-1]
+ self.frontier = self.frontier[:-1]
+ return node
+
+class QueueFrontier(StackFrontier):
+ def remove(self):
+ if self.empty():
+ raise Exception("empty frontier")
+ else:
+ node = self.frontier[0]
+ self.frontier = self.frontier[1:]
+ return node
+
+class gbfsFrontier(StackFrontier):
+ def remove(self):
+ if self.empty():
+ raise Exception("Empty Frontier")
+ else:
+ node = min(self.frontier, key=lambda x: x.heuristic)
+ self.frontier.remove(node)
+ return node
+
+# Create a new class that extends the Graph class
+class GBFSGraph:
+ def __init__(self):
+ self.graph = defaultdict(list)
+
+ def add_edge(self, u, v):
+ self.graph[u].append(v)
+
+ def gbfs(self, start_node, goal_node):
+ visited = [False] * (max(self.graph) + 1)
+ frontier = gbfsFrontier()
+ start_state = Node(start_node, None, None, self.manhattan(start_node, goal_node))
+ frontier.add(start_state)
+
+ while not frontier.empty():
+ node = frontier.remove()
+ state = node.state
+
+ if state == goal_node:
+ path = []
+ while node.parent is not None:
+ path.append(node.state)
+ node = node.parent
+ path.append(start_node)
+ path.reverse()
+ return path
+
+ visited[state] = True
+
+ for neighbor in self.graph[state]:
+ if not visited[neighbor]:
+ heuristic = self.manhattan(neighbor, goal_node)
+ neighbor_state = Node(neighbor, node, None, heuristic)
+ frontier.add(neighbor_state)
+
+ return None
+
+ def manhattan(self, node, goal_node):
+ x1, y1 = node % 3, node // 3
+ x2, y2 = goal_node % 3, goal_node // 3
+ return abs(x1 - x2) + abs(y1 - y2)
+
+# Example usage with user input:
+gbfs_graph = GBFSGraph()
+
+# Get user input for defining the graph
+while True:
+ u = int(input("Enter edge source node (or -1 to stop): "))
+ if u == -1:
+ break
+ v = int(input("Enter edge target node: "))
+ gbfs_graph.add_edge(u, v)
+
+# Get user input for the start and goal nodes
+start_node = int(input("Enter the start node: "))
+goal_node = int(input("Enter the goal node: "))
+
+print(f"GBFS starting from node {start_node} to reach node {goal_node}:")
+path = gbfs_graph.gbfs(start_node, goal_node)
+if path:
+ print("Path:", path)
+else:
+ print("No path found")
diff --git a/Graphs/Kruskals_Algorithm.py b/Graphs/Kruskals_Algorithm.py
new file mode 100644
index 0000000..7a3bd34
--- /dev/null
+++ b/Graphs/Kruskals_Algorithm.py
@@ -0,0 +1,118 @@
+#Kruskal's Algorithm seeks a minimum spanning tree using a greedy approach.
+#Greedy Approach: Selects edges in ascending order of weight, adding them to the MST if they avoid cycles.
+#Edge Sorting: Begins by sorting edges by weight in non-decreasing order.
+#Disjoint Set Data Structure: Utilizes Union-Find to efficiently manage connected components and prevent cycles.
+#Iterative Process: Adds edges to the MST iteratively, starting with the smallest weight edges, until V-1 edges are included (V is the number of vertices).
+#Safe Edge Selection: Ensures edges don't create cycles before adding them to the MST.
+#Efficiency: Kruskal's Algorithm has O(E log E) time complexity, making it suitable for sparse graphs.
+#Applications: Widely used in network design for road networks, electrical circuits, data center connections, and also in clustering and image segmentation.
+
+class KruskalMST:
+ def __init__(self, vertices):
+ """
+ Initialize a KruskalMST object with the given number of vertices.
+
+ Args:
+ vertices (int): The number of vertices in the graph.
+ """
+ self.V = vertices
+ self.graph = []
+
+ def add_edge(self, u, v, w):
+ """
+ Add an edge to the graph.
+
+ Args:
+ u (int): The source vertex.
+ v (int): The destination vertex.
+ w (int): The weight of the edge.
+ """
+ self.graph.append([u, v, w])
+
+ def find(self, parent, i):
+ """
+ Find the parent of a vertex using the union-find algorithm.
+
+ Args:
+ parent (list): A list representing the parent of each vertex.
+ i (int): The vertex to find the parent of.
+
+ Returns:
+ int: The parent of the vertex.
+ """
+ if parent[i] == i:
+ return i
+ return self.find(parent, parent[i])
+
+ def union(self, parent, rank, x, y):
+ """
+ Union operation to merge two subsets into one.
+
+ Args:
+ parent (list): A list representing the parent of each vertex.
+ rank (list): A list representing the rank of each subset.
+ x (int): The root of the first subset.
+ y (int): The root of the second subset.
+ """
+ root_x = self.find(parent, x)
+ root_y = self.find(parent, y)
+
+ if rank[root_x] < rank[root_y]:
+ parent[root_x] = root_y
+ elif rank[root_x] > rank[root_y]:
+ parent[root_y] = root_x
+ else:
+ parent[root_x] = root_y
+ rank[root_y] += 1
+
+ def kruskal(self):
+ """
+ Find the minimum spanning tree using Kruskal's algorithm.
+
+ Returns:
+ list: A list of edges in the minimum spanning tree, represented as [u, v, w], where u and v are vertices
+ and w is the edge weight.
+ """
+ result = []
+ self.graph = sorted(self.graph, key=lambda item: item[2])
+ parent = [i for i in range(self.V)]
+ rank = [0] * self.V
+ i = 0
+ e = 0
+ while e < self.V - 1:
+ u, v, w = self.graph[i]
+ i += 1
+ x = self.find(parent, u)
+ y = self.find(parent, v)
+ if x != y:
+ e += 1
+ result.append([u, v, w])
+ self.union(parent, rank, x, y)
+ return result
+
+
+def main():
+ """
+ Main function to execute the Kruskal's algorithm for finding the Minimum Spanning Tree.
+
+ The function prompts the user for input regarding the number of vertices, number of edges, and edge details.
+ It then prints the edges of the Minimum Spanning Tree.
+ """
+ num_vertices = int(input("Enter the number of vertices: "))
+ g = KruskalMST(num_vertices)
+
+ num_edges = int(input("Enter the number of edges: "))
+ for _ in range(num_edges):
+ u, v, w = map(int, input("Enter edge (u v w): ").split())
+ g.add_edge(u, v, w)
+
+ mst = g.kruskal()
+
+ print("Edges in Minimum Spanning Tree:")
+ for u, v, w in mst:
+ print(f"{u} - {v}: {w}")
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/Graphs/Prims_Algorithm_Minimum_Spanning_Tree.py b/Graphs/Prims_Algorithm_Minimum_Spanning_Tree.py
new file mode 100644
index 0000000..3063708
--- /dev/null
+++ b/Graphs/Prims_Algorithm_Minimum_Spanning_Tree.py
@@ -0,0 +1,59 @@
+//Prim's Algo to calculate the minimum spanning tree with user-input, using the Fibonacci Heap Method.
+
+import sys
+import heapq
+
+class UniqueGraph:
+ def __init(self, vertices_count):
+ self.V = vertices_count
+ self.edges = [[] for _ in range(vertices_count)]
+
+ def find_min_edge(self, key_values, mst_set):
+ min_value = sys.maxsize
+ min_index = 0
+
+ for vertex in range(self.V):
+ if key_values[vertex] < min_value and not mst_set[vertex]:
+ min_value = key_values[vertex]
+ min_index = vertex
+
+ return min_index
+
+ def find_minimum_spanning_tree(self):
+ parents = [None] * self.V
+ key_values = [sys.maxsize] * self.V
+ key_values[0] = 0
+ mst_set = [False] * self.V
+
+ parents[0] = -1
+ min_heap = [(0, 0)]
+
+ while min_heap:
+ current_value, current_vertex = heapq.heappop(min_heap)
+ mst_set[current_vertex] = True
+
+ for edge in self.edges[current_vertex]:
+ adjacent_vertex, weight = edge
+ if not mst_set[adjacent_vertex] and key_values[adjacent_vertex] > weight:
+ key_values[adjacent_vertex] = weight
+ parents[adjacent_vertex] = current_vertex
+ heapq.heappush(min_heap, (key_values[adjacent_vertex], adjacent_vertex))
+
+ self.print_minimum_spanning_tree(parents, key_values)
+
+ def print_minimum_spanning_tree(self, parents, key_values):
+ print("Edge \tWeight")
+ for vertex in range(1, self.V):
+ print(f"{parents[vertex]} - {vertex}\t{key_values[vertex]}")
+
+# Input the graph from the user
+V = int(input("Enter the number of vertices: "))
+g = UniqueGraph(V)
+print("Enter the edges and their weights (e.g., '1 2 3' means an edge from vertex 1 to vertex 2 with weight 3):")
+
+for _ in range(V - 1):
+ u, v, w = map(int, input().split())
+ g.edges[u].append((v, w))
+ g.edges[v].append((u, w))
+
+g.find_minimum_spanning_tree()
diff --git a/Graphs/Tarjan's_Algorithm.py b/Graphs/Tarjan's_Algorithm.py
new file mode 100644
index 0000000..cc88b01
--- /dev/null
+++ b/Graphs/Tarjan's_Algorithm.py
@@ -0,0 +1,82 @@
+""" "defaultdict" in Python
+ is a dictionary-like container from the collections
+module that provides a default value for keys that do not exist."""
+
+from collections import defaultdict
+
+# Function to run Tarjan's algorithm
+def tarjan(graph):
+
+ index = 0
+ stack = []
+ components = []
+
+ # Track visited and index for each node
+ indexes = {}
+ lowlinks = {}
+
+ def strongconnect(node):
+
+ # Set the depth index for this node to the smallest unused index
+ nonlocal index
+ indexes[node] = index
+ lowlinks[node] = index
+ index += 1
+ stack.append(node)
+
+ # Consider successors of `node`
+ try:
+ successors = graph[node]
+ except:
+
+ successors = []
+ for successor in successors:
+ if successor not in indexes:
+ # Successor has not yet been visited; recurse on it
+ strongconnect(successor)
+ lowlinks[node] = min(lowlinks[node], lowlinks[successor])
+ elif successor in stack:
+ # Successor is in the stack, hence in the current SCC
+ lowlinks[node] = min(lowlinks[node], indexes[successor])
+
+ # If `node` is a root node, pop the stack and generate an SCC
+ if lowlinks[node] == indexes[node]:
+ connected_component = []
+
+ while True:
+ successor = stack.pop()
+ connected_component.append(successor)
+ if successor == node:
+ break
+ components.append(connected_component)
+
+ for node in graph:
+ if node not in indexes:
+ strongconnect(node)
+
+ return components
+
+# Accept dynamic input for the graph
+graph = defaultdict(list)
+num_nodes = int(input("Enter the number of nodes: "))
+for i in range(num_nodes):
+ node = int(input(f"Enter the successors of node {i}: "))
+ successors = list(map(int, input().split()))
+ graph[node] = successors
+
+print("Strongly Connected Components:")
+print(tarjan(graph))
+
+
+
+""" Explanation:->
+
+1) Tarjan's algorithm performs a DFS on the graph to find strongly connected components.
+
+2) It maintains an index (incremented for each visited node), a stack of visited nodes, and a lowlink value for each node (lowest index reachable from that node).
+
+3) When visiting a node, if any successor is in the stack, the lowlink is updated to be the minimum of its current value and the successor's index.
+
+4) If the lowlink of a node equals its own index, it is a root node and the current stack represents an SCC. This SCC is popped from the stack and added to the final components list.
+
+5) After Tarjan's finishes, the components list contains all the SCCs in the graph."""
\ No newline at end of file
diff --git a/Graphs/Travelling_Salesman_Problem.py b/Graphs/Travelling_Salesman_Problem.py
new file mode 100644
index 0000000..db79c29
--- /dev/null
+++ b/Graphs/Travelling_Salesman_Problem.py
@@ -0,0 +1,150 @@
+from itertools import permutations
+
+def calculate_total_distance(path, distances):
+ """
+ Calculate the total distance of a path through cities.
+
+ Args:
+ path (list of int): A list representing the order of cities to visit.
+ distances (list of lists of int): A distance matrix between cities.
+
+ Returns:
+ int: The total distance of the path.
+
+ Example:
+ >>> distances = [[0, 2, 9, 10], [1, 0, 6, 4], [15, 7, 0, 8], [6, 3, 12, 0]]
+ >>> calculate_total_distance([0, 1, 2, 3, 0], distances)
+ 21
+ """
+ total_distance = 0
+ for i in range(len(path) - 1):
+ total_distance += distances[path[i]][path[i + 1]]
+ total_distance += distances[path[-1]][path[0]]
+ return total_distance
+
+def traveling_salesman_bruteforce(distances):
+ """
+ Find the shortest path through cities using brute force.
+
+ Args:
+ distances (list of lists of int): A distance matrix between cities.
+
+ Returns:
+ tuple: A tuple containing the shortest path (list of int) and the shortest distance (int).
+
+ Example:
+ >>> distances = [[0, 2, 9, 10], [1, 0, 6, 4], [15, 7, 0, 8], [6, 3, 12, 0]]
+ >>> traveling_salesman_bruteforce(distances)
+ ([0, 1, 3, 2], 21)
+ """
+ num_cities = len(distances)
+ all_cities = list(range(num_cities))
+ shortest_path = None
+ shortest_distance = float('inf')
+
+ for path in permutations(all_cities):
+ distance = calculate_total_distance(path, distances)
+ if distance < shortest_distance:
+ shortest_distance = distance
+ shortest_path = path
+
+ return shortest_path, shortest_distance
+
+def create_distance_matrix(num_cities):
+ """
+ Create a distance matrix for a given number of cities.
+
+ Args:
+ num_cities (int): The number of cities.
+
+ Returns:
+ list of lists of int: A distance matrix between cities.
+
+ Example:
+ >>> create_distance_matrix(4)
+ [[0, 2, 9, 10], [2, 0, 6, 4], [9, 6, 0, 8], [10, 4, 8, 0]]
+ """
+ distances = []
+ for i in range(num_cities):
+ row = []
+ for j in range(num_cities):
+ if i == j:
+ row.append(0)
+ elif j > i:
+ distance = int(input(f"Enter distance between City {i + 1} and City {j + 1}: "))
+ row.append(distance)
+ else:
+ row.append(distances[j][i])
+ distances.append(row)
+ return distances
+
+def print_distance_matrix(distances):
+ """
+ Print the distance matrix.
+
+ Args:
+ distances (list of lists of int): A distance matrix between cities.
+
+ Example:
+ >>> distances = [[0, 2, 9, 10], [1, 0, 6, 4], [15, 7, 0, 8], [6, 3, 12, 0]]
+ >>> print_distance_matrix(distances)
+ Distance Matrix:
+ [0, 2, 9, 10]
+ [2, 0, 6, 4]
+ [9, 6, 0, 8]
+ [10, 4, 8, 0]
+ """
+ print("Distance Matrix:")
+ for row in distances:
+ print(row)
+
+def print_city_path(path):
+ """
+ Print the shortest path through cities.
+
+ Args:
+ path (list of int): A list representing the order of cities to visit.
+
+ Example:
+ >>> print_city_path([0, 1, 3, 2])
+ Shortest Path: City 1 -> City 2 -> City 4 -> City 3
+ """
+ city_path = [f"City {city + 1}" for city in path]
+ print("Shortest Path:", " -> ".join(city_path)
+
+def main_menu():
+ """
+ Display a menu for the traveling salesman problem and handle user input.
+
+ Example:
+ >>> # This function interacts with the user, so no specific doctests are provided.
+ >>> # You can run this function manually to test the menu functionality.
+ >>> main_menu()
+ """
+ while True:
+ print("\nMenu:")
+ print("1. Create a distance matrix")
+ print("2. Find the shortest path")
+ print("3. Exit")
+
+ choice = input("Enter your choice: ")
+
+ if choice == '1':
+ num_cities = int(input("Enter the number of cities: "))
+ distances = create_distance_matrix(num_cities)
+ print_distance_matrix(distances)
+ elif choice == '2':
+ if 'distances' in locals():
+ shortest_path, shortest_distance = traveling_salesman_bruteforce(distances)
+ print_city_path(shortest_path)
+ print("Shortest Distance:", shortest_distance)
+ else:
+ print("Please create a distance matrix first.")
+ elif choice == '3':
+ print("Goodbye!")
+ break
+ else:
+ print("Invalid choice. Please select a valid option.")
+
+if __name__ == "__main__":
+ main_menu()
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Circular_Doubly_LinkedList.py b/Linked List/Menu_Driven_Code_for_Circular_Doubly_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Circular_Doubly_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Circular_Doubly_LinkedList.py
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Circular_LinkedList.py b/Linked List/Menu_Driven_Code_for_Circular_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Circular_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Circular_LinkedList.py
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Doubly_LinkedList.py b/Linked List/Menu_Driven_Code_for_Doubly_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Doubly_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Doubly_LinkedList.py
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py b/Linked List/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Dynamic_Stack_using_LinkedList.py b/Linked List/Menu_Driven_Code_for_Dynamic_Stack_using_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Dynamic_Stack_using_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Dynamic_Stack_using_LinkedList.py
diff --git a/Codes/Linked List/Menu_Driven_Code_for_Linear_LinkedList.py b/Linked List/Menu_Driven_Code_for_Linear_LinkedList.py
similarity index 100%
rename from Codes/Linked List/Menu_Driven_Code_for_Linear_LinkedList.py
rename to Linked List/Menu_Driven_Code_for_Linear_LinkedList.py
diff --git a/Math/Prefix_Sum.py b/Math/Prefix_Sum.py
new file mode 100644
index 0000000..4bfa726
--- /dev/null
+++ b/Math/Prefix_Sum.py
@@ -0,0 +1,25 @@
+# Function to calculate the prefix sum of a list using list comprehension
+def calculatePrefixSum(arr):
+ prefixSum = [sum(arr[:i + 1]) for i in range(len(arr))]
+ return prefixSum
+
+def main():
+ # Input the list size
+ n = int(input("Enter the size of the list: "))
+
+ if n <= 0:
+ print("List size must be a positive integer.")
+ return 1 # Exit with an error code
+
+ # Input the elements of the list
+ print(f"Enter {n} elements of the list:")
+ arr = [int(input()) for _ in range(n)]
+
+ # Calculate the prefix sum
+ prefixSum = calculatePrefixSum(arr)
+
+ # Display the prefix sum
+ print("Prefix Sum:", prefixSum)
+
+if __name__ == "__main__":
+ main()
diff --git a/Math/kadane's_algorithm.py b/Math/kadane's_algorithm.py
new file mode 100644
index 0000000..dcc8858
--- /dev/null
+++ b/Math/kadane's_algorithm.py
@@ -0,0 +1,17 @@
+def max_subarray_sum(nums):
+ # Initialize variables to keep track of the maximum subarray sum
+
+ max_ending_here = nums[0] # Maximum sum ending at the current position
+ max_so_far = nums[0] # Maximum sum seen so far
+
+ # Iterate through the array, starting from the second element
+ for i in range(1, len(nums)):
+ # Calculate the maximum sum ending at the current position by considering whether it's better to
+ # start a new subarray or extend the previous one.
+ max_ending_here = max(nums[i], max_ending_here + nums[i])
+
+ # Update the maximum sum seen so far by comparing it with the maximum sum ending at the current position.
+ max_so_far = max(max_so_far, max_ending_here)
+
+ # The 'max_so_far' variable now contains the maximum subarray sum.
+ return max_so_far
\ No newline at end of file
diff --git a/Math/sieve_of_eratosthenes.py b/Math/sieve_of_eratosthenes.py
new file mode 100644
index 0000000..88cf490
--- /dev/null
+++ b/Math/sieve_of_eratosthenes.py
@@ -0,0 +1,30 @@
+"""Sieve Of Eratosthenes:
+The sieve of eratosthenes is one of the most efficient way to find all
+the prime numbers upto the number `n`
+
+for more reference(https://www.geeksforgeeks.org/sieve-of-eratosthenes/)
+"""
+
+#importing `math` module which will be used later
+import math
+
+#specify upto where you have to find the prime numbers
+n = int(input("Enter the range : "))
+
+#`arr` is a boolean list that contains `n+1` `False` entries
+arr = [False]*(n+1)
+
+#loop upto the square root of the range `n`
+for i in range(2,int(math.sqrt(n))+1):
+ if arr[i] == False:
+ for j in range(i*i, n+1, i):
+ #making the entry `True` for all entries whose index is the multiple
+ arr[j] = True
+
+#after the loop exits, all the entry that are prime numbers
+#are marked as `False`
+
+#printing all the prime numbers
+for i in range(2,n):
+ if arr[i+1] == False:
+ print(i+1)
diff --git a/Codes/Queue/Menu_Driven_Code_for_Circular_Queue.py b/Queue/Menu_Driven_Code_for_Circular_Queue.py
similarity index 100%
rename from Codes/Queue/Menu_Driven_Code_for_Circular_Queue.py
rename to Queue/Menu_Driven_Code_for_Circular_Queue.py
diff --git a/Codes/Queue/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py b/Queue/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
similarity index 100%
rename from Codes/Queue/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
rename to Queue/Menu_Driven_Code_for_Dynamic_Linear_Queue_using_LinkedList.py
diff --git a/Codes/Queue/Menu_Driven_Code_for_Linear_Queue.py b/Queue/Menu_Driven_Code_for_Linear_Queue.py
similarity index 100%
rename from Codes/Queue/Menu_Driven_Code_for_Linear_Queue.py
rename to Queue/Menu_Driven_Code_for_Linear_Queue.py
diff --git a/Codes/Queue/Menu_Driven_Code_for_Priority_Queue.py b/Queue/Menu_Driven_Code_for_Priority_Queue.py
similarity index 100%
rename from Codes/Queue/Menu_Driven_Code_for_Priority_Queue.py
rename to Queue/Menu_Driven_Code_for_Priority_Queue.py
diff --git a/Queue/Menu_Driven_Code_for_Priority_Queue_Heap_implementation.py b/Queue/Menu_Driven_Code_for_Priority_Queue_Heap_implementation.py
new file mode 100644
index 0000000..c6e19d3
--- /dev/null
+++ b/Queue/Menu_Driven_Code_for_Priority_Queue_Heap_implementation.py
@@ -0,0 +1,117 @@
+class Q:
+ queue = []
+ MaxSize = 0
+ currSize = 0
+
+ def createQueue(self, size):
+ Q.MaxSize = size
+ Q.currSize = 0
+ for i in range(0, Q.MaxSize):
+ Q.queue.append(0)
+ print('\nQueue created of size: ', len(Q.queue))
+ print(Q.queue)
+
+ def enqueue(self, e):
+ Q.currSize += 1
+ Q.queue[Q.currSize-1] = e
+ Q.shiftUp(Q.currSize-1)
+ print(e, 'enqueued in Queue')
+ print('')
+
+ def dequeue(self):
+ temp = Q.queue[0]
+ Q.currSize -= 1
+ Q.queue[0] = Q.queue[Q.currSize]
+ Q.shiftDown(0)
+ print(temp, 'dequeued from Queue')
+ print('')
+
+ def isFull(self):
+ if Q.currSize == Q.MaxSize:
+ return True
+ else:
+ return False
+
+ def isEmpty(self):
+ if Q.currSize == 0:
+ return True
+ else:
+ return False
+
+ def printQueue(self):
+ print('Position', '\tData')
+ for i in range(Q.currSize):
+ print(i+1,'\t\t',Q.queue[i])
+
+ def shiftUp(i) :
+ parent = (i - 1) // 2
+ while (i > 0 and Q.queue[parent] < Q.queue[i]) :
+
+ # Swap parent and current node
+ (Q.queue[i], Q.queue[parent]) = (Q.queue[parent], Q.queue[i]) # swap
+
+ # Update i to parent of i
+ i = parent
+ parent = (i - 1) // 2
+
+ def shiftDown(i):
+ largest = i # Initialize largest as root
+ l = 2 * i + 1 # left = 2*i + 1
+ r = 2 * i + 2 # right = 2*i + 2
+
+ # See if left child of root exists and is
+ # greater than root
+
+ if l < Q.currSize and Q.queue[i] < Q.queue[l]:
+ largest = l
+
+ # See if right child of root exists and is
+ # greater than root
+
+ if r < Q.currSize and Q.queue[largest] < Q.queue[r]:
+ largest = r
+
+ # Change root, if needed
+
+ if largest != i:
+ (Q.queue[i], Q.queue[largest]) = (Q.queue[largest], Q.queue[i]) # swap
+ Q.shiftDown(largest)
+
+
+
+# Main Code:
+
+o = Q()
+o.createQueue(int(input('Enter size of the queue: ')))
+
+while True:
+ print('------------')
+ print('1.Enqueue\n2.Dequeue\n3.Print\n0.Exit')
+ print('------------')
+
+ ch = int(input('\nEnter your choice: '))
+
+ if ch == 1:
+ if o.isFull() != True:
+ data = int(input('\nEnter data to be enqueued: '))
+ o.enqueue(data)
+ else:
+ print('\nQueue is full..\n')
+
+ elif ch == 2:
+ if o.isEmpty() != True:
+ o.dequeue()
+ else:
+ print('\nQueue is empty..\n')
+
+ elif ch == 3:
+ if o.isEmpty() != True:
+ o.printQueue()
+ else:
+ print('\nQueue is empty..\n')
+
+ elif ch == 0:
+ break
+
+ else:
+ print('\nWrong Input..\nEnter the correct choice..!!\n')
\ No newline at end of file
diff --git a/README.md b/README.md
index 7f7e81f..e24dec8 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,75 @@
-# Python-Data-Structures
-A compilation of Data Structures in Python. It is a collection of Python code examples and implementations of various data structures. This repository aims to provide a comprehensive resource for understanding and utilizing different data structures efficiently in Python.
+
-    
-
   
-
   
-
   
-
-
+
   
+
   
+
   
+
   
+
   
+