diff --git a/algorithms/cryptography/Hill_cipher.py b/algorithms/cryptography/Hill_cipher.py new file mode 100644 index 0000000..943c463 --- /dev/null +++ b/algorithms/cryptography/Hill_cipher.py @@ -0,0 +1,42 @@ +import numpy as np +s=list(input("Enter a string")) +c=[] +for i in range(len(s)): + c.append(ord(s[i])-65) + +arr= np.array(c) + +a1=np.transpose(arr) +print(a1) +a1= a1.reshape(3,1) +print(a1.shape) + + +#key input +print("Enter the key for the encryption") +R = int(input("rows:")) +C = int(input("columns:")) +matrix = [] +print("Enter the key:") + +for i in range(R): + a =[] + for j in range(C): + a.append(int(input())) + matrix.append(a) + +for i in range(R): + for j in range(C): + print(matrix[i][j], end = " ") +matrix = np.array(matrix) +print(matrix.shape) +print(matrix[1][1]) + +mul=np.matmul(matrix,a1) +mul = np.array(mul) +print(mul.shape) +print(mul) +for i in range(R): + mul[i]=mul[i]%26 + +print(mul) diff --git a/algorithms/cryptography/railfence_cipher.py b/algorithms/cryptography/railfence_cipher.py new file mode 100644 index 0000000..0cdf24a --- /dev/null +++ b/algorithms/cryptography/railfence_cipher.py @@ -0,0 +1,78 @@ +def railencrypt(st,k): + c = 0 + x = 0 + m =[[0] * (len(st)) for i in range(k)] + for r in range(len(st)): + m[c][r] = st[r] + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + + result = [] + for i in range(k): + for j in range(len(st)): + if m[i][j] != 0: + result.append(m[i][j]) + print("CipherText:","" . join(result)) + +def raildecrypt(st,k): + c , x = 0 , 0 + m =[[0] * (len(st)) for i in range(k)] + for r in range(len(st)): + m[c][r] = 1 + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + result = [] + c , x = 0 , 0 + for i in range(k): + for j in range(len(st)): + if m[i][j] == 1: + m[i][j] = st[x] + x += 1 + for r in range(len(st)): + if m[c][r] != 0: + result.append(m[c][r]) + if x == 0: + if c == (k-1): + x = 1 + c -= 1 + else: + c += 1 + else: + if c == 0: + x = 0 + c += 1 + else: + c -= 1 + print("PlainText:","" . join(result)) + +if __name__ == "__main__": + string = input("Enter the Message:") + string = string.upper() + key = int(input("Enter the Key:")) + n = int(input("1.Encryption\n2.Decryption\nInput Your choice:")) + if(n == 1): + railencrypt(string,key) + elif(n == 2): + raildecrypt(string,key) + else: + print("Error") diff --git a/algorithms/data-structures/trees/size_of_subtree.py b/algorithms/data-structures/trees/size_of_subtree.py new file mode 100644 index 0000000..eb594f0 --- /dev/null +++ b/algorithms/data-structures/trees/size_of_subtree.py @@ -0,0 +1,28 @@ +""" + This is an efficient algorithm to find the size of a subtree from every node in O(n) time. + The idea is to use one dfs and first calculate the size of subtree of children of a node recursively. + Then add the size of each subtree of its children to get the size of its subtree. +""" +from collections import defaultdict as dd + + +def dfs(source, parent): + # Initial size of root is 1 + size[source] = 1 + for child in graph[source]: + if child != parent: + # Recursively calculate size of subtree of children nodes + dfs(child, source) + # Adding size of each child's subtree. + size[source] += size[child] + + +size = dd(int) +graph = dd(set) +n = int(input()) +for i in range(n-1): + u, v = map(int, input().split()) + graph[u].add(v) + graph[v].add(u) +dfs(1, 0) +print(size) diff --git a/algorithms/divide-and-conquer/mergesort.py b/algorithms/divide-and-conquer/mergesort.py new file mode 100644 index 0000000..05e5a0b --- /dev/null +++ b/algorithms/divide-and-conquer/mergesort.py @@ -0,0 +1,26 @@ +def merge(left_subarray,right_subarray): + i,j = 0,0 + result = [] + + while i partialSum + array[i]: + partialSum = array[i] + fromIndex = i + else: + partialSum += array[i] + + if partialSum >= bestSum: + bestSum = partialSum + toIndex = i + + return { + "fromIndex" : fromIndex, + "toIndex" : toIndex, + "bestSum" : bestSum + } + +n = int(input("Enter the size of the array: ")) +print("Input the array") +array = map(int,raw_input().split()) + +kadane = Kadane(array) +print("Sum: %d From: %d To: %d" % (kadane['bestSum'], kadane['fromIndex'], kadane['toIndex'])) \ No newline at end of file diff --git a/algorithms/linkedlist/find_length_linkedList.py b/algorithms/linkedlist/find_length_linkedList.py new file mode 100644 index 0000000..7fe4cf7 --- /dev/null +++ b/algorithms/linkedlist/find_length_linkedList.py @@ -0,0 +1,56 @@ +# A complete working Python program to find length of a +# Linked List iteratively + +# Node class +class Node: + # Function to initialise the node object + def __init__(self, data): + self.data = data # Assign data + self.next = None # Initialize next as null + + +# Linked List class contains a Node object +class LinkedList: + + # Function to initialize head + def __init__(self): + self.head = None + + + # This function is in LinkedList class. It inserts + # a new node at the beginning of Linked List. + def push(self, new_data): + + # 1 & 2: Allocate the Node & + # Put in the data + new_node = Node(new_data) + + # 3. Make next of new Node as head + new_node.next = self.head + + # 4. Move the head to point to new Node + self.head = new_node + + + # This function counts number of nodes in Linked List + # iteratively, given 'node' as starting node. + def getCount(self): + temp = self.head # Initialise temp + count = 0 # Initialise count + + # Loop while end of linked list is not reached + while (temp): + count += 1 + temp = temp.next + return count + + +# Code execution starts here +if __name__=='__main__': + llist = LinkedList() + llist.push(1) + llist.push(3) + llist.push(1) + llist.push(2) + llist.push(1) + print ("Count of nodes is :",llist.getCount()) diff --git a/algorithms/recursion/Factorial By Recursion Python.py b/algorithms/recursion/Factorial By Recursion Python.py new file mode 100644 index 0000000..25ec0d6 --- /dev/null +++ b/algorithms/recursion/Factorial By Recursion Python.py @@ -0,0 +1,11 @@ +#FINDING FACTORIAL THROUGH RECURSION +def recursion(n): + if(n==0): + return 1 + else: + return n*recursion(n-1) +a=int(input("Enter The Number You Want The Factorial Of")) #Asking User The Number for the factorial +if(a>=0): # Checking if the Number is positive or not + print(recursion()) +else: + print("Enter Valid Positive Number") diff --git a/algorithms/recursion/Fibonacci-Series-by-python.py b/algorithms/recursion/Fibonacci-Series-by-python.py new file mode 100644 index 0000000..33bf3a3 --- /dev/null +++ b/algorithms/recursion/Fibonacci-Series-by-python.py @@ -0,0 +1,13 @@ + +### Program to calculate fibonacci series + +def fibo(n): // function to calculate fibonacci series + if(n == 0): + return 0 + elif(n == 1): + return 1 + else: + return(fibo(n-1) + fibo(n-2)) +num = int(input("Enter a number: ")) // enter number upto which you want to calculate fibonacci series +for n in range(0,(num+1)): + print(fibo(n),end=" ") diff --git a/algorithms/recursion/exponentiation.py b/algorithms/recursion/exponentiation.py new file mode 100644 index 0000000..5709894 --- /dev/null +++ b/algorithms/recursion/exponentiation.py @@ -0,0 +1,21 @@ + +def exponentiation(baseNumber, power): + answer = None + + if power > 1: + halfAnswer = exponentiation(baseNumber, power//2) + answer = halfAnswer * halfAnswer + + if power%2 == 1: + answer *= baseNumber + + elif power == 1: + answer = baseNumber + + elif power == 0: + answer = 1 + + else: # negative power + answer = 1 / exponentiation(baseNumber, abs(power)) + + return answer diff --git a/algorithms/sorting/cocktail_sort.py b/algorithms/sorting/cocktail_sort.py new file mode 100644 index 0000000..71f7b38 --- /dev/null +++ b/algorithms/sorting/cocktail_sort.py @@ -0,0 +1,26 @@ +def cocktailSort(array) + n = len(array) + swap = 1 + begin = 0 + end = n-1 + #Sorting start + while (swap == 1): + swap = 0 + + #sorting from begin + for i in range (begin, end): + if (a[i] > a[i+1]) : + a[i], a[i+1]= a[i+1], a[i] + swap=1 + + if (swap==0): + break swap = 0 + + end = end-1 + #sorting from end + for i in range(end-1, begin-1,-1): + if (a[i] > a[i+1]): + a[i], a[i+1] = a[i+1], a[i] + swap = 1 + + begin = begin+1 \ No newline at end of file diff --git a/algorithms/sorting/tim_sort.py b/algorithms/sorting/tim_sort.py new file mode 100644 index 0000000..993c07e --- /dev/null +++ b/algorithms/sorting/tim_sort.py @@ -0,0 +1,90 @@ +from random import randint + + +class TimSort: + """ A class to demonstrate Tim Sort """ + + def __init__(self, array): + self.array = array + self.arrayLength = len(array) + self.__RUN = 32 + + def insertionSort(self, arr): + """ Sorts the given array from given starting index to ending index """ + + for i in range(1, len(arr)): + currentElement = arr[i] + j = i - 1 + while j >= 0 and arr[j] > currentElement: + arr[j + 1] = arr[j] + j -= 1 + arr[j + 1] = currentElement + + return arr + + def mergeRuns(self, arr1, arr2): + """ Merges the given two arrays: arr1 and arr2 """ + + newArray = list() + lengthOfArr1 = len(arr1) + lengthOfArr2 = len(arr2) + + # The variable i is used to keep track of the indices of the first array + # The variable j is used to keep track of the indices of the second array + # The variable k is used to keep track of the indices of the newArray array which is to be returned + i, j, k = 0, 0, 0 + + while i < lengthOfArr1 and j < lengthOfArr2: + if arr1[i] <= arr2[j]: + newArray[k] = arr1[i] + k += 1 + i += 1 + elif arr1[i] >= arr2[j]: + newArray[k] = arr2[j] + k += 1 + j += 1 + + # The below two loops will append any remaining elements left in any of the two arrays. + while i < lengthOfArr1: + newArray.append(arr1[i]) + i += 1 + + while j < lengthOfArr2: + newArray.append(arr2[j]) + j += 1 + + return newArray + + def changeRun(self, newRun): + self.__RUN = newRun + + def algorithm(self): + """ This function will perfom Tim Sort on the given array """ + + # Breaking the array into chunks of subarray(RUNS) of size RUN and perfomring insertionSort on them. + for i in range(0, self.arrayLength, self.__RUN): + currentRunElements = self.array[i: i + self.__RUN] + + self.array[i: i + + self.__RUN] = self.insertionSort(currentRunElements) + + temp_runner = self.__RUN + while temp_runner < self.arrayLength: + for idx in range(0, self.arrayLength, temp_runner * 2): + firstArray = self.array[idx: idx + temp_runner] + secondArray = self.array[idx + + temp_runner: idx + temp_runner * 2] + self.array[idx: idx + temp_runner * + 2] = self.mergeRuns(firstArray, secondArray) + temp_runner = self.__RUN * 2 + + print(f"The sorted array is : {self.array}") + + def __repr__(self): + return f"Array: {self.array}\nRUN: {self.__RUN}" + + +myArray = [randint(1, 100) for i in range(15)] +demo = TimSort(myArray) +print(demo) +demo.algorithm() diff --git a/algorithms/strings/levenstein.py b/algorithms/strings/levenstein.py new file mode 100644 index 0000000..66ad47d --- /dev/null +++ b/algorithms/strings/levenstein.py @@ -0,0 +1,9 @@ +def distance_levenstein(a, b): + f = [[(i+j) if i*j == 0 else 0 for j in range(len(b)+1)] for i in range(len(a) + 1)] + for i in range(1, len(a) + 1): + for j in range(1, len(b) + 1): + if a[i-1] == b[j-1]: + f[i][j] = f[i-1][j-1] + else: + f[i][j] = 1 + min(f[i-1][j], f[i][j-1], f[i-1][j-1]) + return f[len(a)][len(b)] diff --git a/classification/fcm.py b/classification/fcm.py new file mode 100644 index 0000000..79a3ee9 --- /dev/null +++ b/classification/fcm.py @@ -0,0 +1,57 @@ +from tools import * + +# https://en.wikipedia.org/wiki/Fuzzy_clustering + + +class FuzzyCMeans: + def __init__(self, n_clusters, initial_centers, data, max_iter=250, m=2, error=1e-5): + assert m > 1 + #assert initial_centers.shape[0] == n_clusters + self.U = None + self.centers = initial_centers + self.max_iter = max_iter + self.m = m + self.error = error + self.data = data + + def membership(self, data, centers): + U_temp = cdist(data, centers, 'euclidean') + U_temp = numpy.power(U_temp, 2/(self.m - 1)) + denominator_ = U_temp.reshape( + (data.shape[0], 1, -1)).repeat(U_temp.shape[-1], axis=1) + denominator_ = U_temp[:, :, numpy.newaxis] / denominator_ + return 1 / denominator_.sum(2) + + def Centers(self, data, U): + um = U ** self.m + return (data.T @ um / numpy.sum(um, axis=0)).T + + def newImage(self, U, centers, im): + best = numpy.argmax(self.U, axis=-1) + # print(best) + # numpy.round() + image = im.astype(int) + for i in range(256): + image = numpy.where(image == float(i), centers[best[i]][0], image) + return image + + def compute(self): + self.U = self.membership(self.data, self.centers) + + past_U = numpy.copy(self.U) + begin_time = datetime.datetime.now() + for i in range(self.max_iter): + + self.centers = self.Centers(self.data, self.U) + self.U = self.membership(self.data, self.centers) + + if norm(self.U - past_U) < self.error: + break + past_U = numpy.copy(self.U) + x = datetime.datetime.now() - begin_time + return self.centers, self.U, x + +# that's how you run it, data being your data, and the other parameters being the basic FCM parameters such as numbe rof cluseters, degree of fuzziness and so on +# f = FuzzyCMeans(n_clusters=C, initial_centers=Initial_centers, +# data=data m=2, max_iter=1000, error=1e-5) +# centers, U, time = f.compute() diff --git a/classification/tools.py b/classification/tools.py new file mode 100644 index 0000000..682268a --- /dev/null +++ b/classification/tools.py @@ -0,0 +1,20 @@ +from matplotlib.image import imread +import matplotlib.pyplot as plt +from math import sqrt +import math +import random +import numpy +import operator +from scipy.spatial.distance import cdist +from scipy.linalg import norm +import datetime + + +def Histogram(path): + image = imread(path) + if len(image.shape) != 2: + def gray(rgb): return numpy.dot(rgb[..., :3], [0.2989, 0.5870, 0.1140]) + gray = gray(image) + image = gray + hist, bins = numpy.histogram(image.ravel(), 256, [0, 256]) + return adapt(hist) diff --git a/data-structures/Array Intersection.py b/data-structures/Array Intersection.py new file mode 100644 index 0000000..86545d5 --- /dev/null +++ b/data-structures/Array Intersection.py @@ -0,0 +1,14 @@ +### Here You can Use this Program For Finding Same elements in two Arrays. +def Array_Inter(arr1,n,arr2,m): ## Here I am Function + for i in range(n) : + for j in range(m) : + if arr1[i] == arr2[j] : + print(arr1[i], end = " ") + break +t=int(input("Test cases: ")) ## take test cases to be run +for k in range(t): + n=int(input("Size of Array One: ")) ## Size of array one by the user + arr1=[int(x) for x in input().split()] ## take inputs from user seperated by space + m=int(input("Size Of Array Two: ")) + arr2=[int(y) for y in input().split()] +Array_Inter(arr1,n,arr2,m) diff --git a/data-structures/InorderTreeTraversal.py b/data-structures/InorderTreeTraversal.py new file mode 100644 index 0000000..4929c7c --- /dev/null +++ b/data-structures/InorderTreeTraversal.py @@ -0,0 +1,50 @@ +class Node: + """A binary tree node""" + def __init__(self, data, left=None, right=None): + self.data = data + self.left = left + self.right = right + + +def morris_traversal(root): + """Generator function for iterative inorder tree traversal""" + + current = root + + while current is not None: + + if current.left is None: + yield current.data + current = current.right + else: + + # Find the inorder predecessor of current + pre = current.left + while pre.right is not None and pre.right is not current: + pre = pre.right + + if pre.right is None: + + # Make current as right child of its inorder predecessor + pre.right = current + current = current.left + + else: + # Revert the changes made in the 'if' part to restore the + # original tree. i.e., fix the right child of predecessor + pre.right = None + yield current.data + current = current.right + +# Driver program to test the above function + +root = Node(1, + right = Node(3), + left = Node(2, + left = Node(4), + right = Node(5) + ) + ) + +for v in morris_traversal(root): + print(v, end=' ') diff --git a/data-structures/binarySerach.py b/data-structures/binarySerach.py new file mode 100644 index 0000000..4169aee --- /dev/null +++ b/data-structures/binarySerach.py @@ -0,0 +1,25 @@ +def binSearch(a, x, low, high): + #Return True if target is found in indicated portion of a Python list. + #The search only considers the portion from data[low] to data[high] inclusive. + + if low > high: + return False # interval is empty; no match + else: + mid = (low + high) // 2 + if x == a[mid]: # found a match + return True + elif x < a[mid]: + # recur on the portion left of the middle + return binSearch(a, x, low, mid - 1) + else: + # recur on the portion right of the middle + return binSearch(a, x, mid + 1, high) +a = [5, 10, 15, 20, 25, 30, 40] +x = 20 +low = 0 +high = 6 +result = binSearch(a, x, low, high) +if result: + print("The value ", x, " Found") +else: + print("The value ", x, " Not found") diff --git a/data-structures/dequeue.py b/data-structures/dequeue.py new file mode 100644 index 0000000..884c698 --- /dev/null +++ b/data-structures/dequeue.py @@ -0,0 +1,48 @@ +class Dequeue: + def __init__(self): + self.items = [] + + def is_empty(self): + return self.items == [] + + def append(self, data): + self.items.append(data) + + def append_left(self, data): + self.items.insert(0, data) + + def pop(self): + return self.items.pop() + + def pop_left(self): + return self.items.pop(0) + + +q = Dequeue() +print('Menu') +print('append ') +print('appendleft ') +print('pop') +print('popleft') +print('quit') + +while True: + do = input('What would you like to do? ').split() + + operation = do[0].strip().lower() + if operation == 'append': + q.append(int(do[1])) + elif operation == 'appendleft': + q.append_left(int(do[1])) + elif operation == 'pop': + if q.is_empty(): + print('Dequeue is empty.') + else: + print('Popped value from right: ', q.pop()) + elif operation == 'popleft': + if q.is_empty(): + print('Dequeue is empty.') + else: + print('Popped value from left: ', q.pop_left()) + elif operation == 'quit': + break \ No newline at end of file diff --git a/data-structures/linked-lists/circulardoublylinkedlist.py b/data-structures/linked-lists/circulardoublylinkedlist.py new file mode 100644 index 0000000..eef2769 --- /dev/null +++ b/data-structures/linked-lists/circulardoublylinkedlist.py @@ -0,0 +1,109 @@ +class Node: + def __init__(self, data): + self.data = data + self.next = None + self.prev = None + + +class CircularDoublyLinkedList: + def __init__(self): + self.first = None + + def get_node(self, index): + current = self.first + for i in range(index): + current = current.next + if current == self.first: + return None + return current + + def insert_after(self, ref_node, new_node): + new_node.prev = ref_node + new_node.next = ref_node.next + new_node.next.prev = new_node + ref_node.next = new_node + + def insert_before(self, ref_node, new_node): + self.insert_after(ref_node.prev, new_node) + + def insert_at_end(self, new_node): + if self.first is None: + self.first = new_node + new_node.next = new_node + new_node.prev = new_node + else: + self.insert_after(self.first.prev, new_node) + + def insert_at_beg(self, new_node): + self.insert_at_end(new_node) + self.first = new_node + + def remove(self, node): + if self.first.next == self.first: + self.first = None + else: + node.prev.next = node.next + node.next.prev = node.prev + if self.first == node: + self.first = node.next + + def display(self): + if self.first is None: + return + current = self.first + while True: + print(current.data, end = ' ') + current = current.next + if current == self.first: + break + + +a_cdllist = CircularDoublyLinkedList() + +print('Menu') +print('insert after ') +print('insert before ') +print('insert at beg') +print('insert at end') +print('remove ') +print('quit') + +while True: + print('The list: ', end = '') + a_cdllist.display() + print() + do = input('What would you like to do? ').split() + + operation = do[0].strip().lower() + + if operation == 'insert': + data = int(do[1]) + position = do[3].strip().lower() + new_node = Node(data) + suboperation = do[2].strip().lower() + if suboperation == 'at': + if position == 'beg': + a_cdllist.insert_at_beg(new_node) + elif position == 'end': + a_cdllist.insert_at_end(new_node) + else: + index = int(position) + ref_node = a_cdllist.get_node(index) + if ref_node is None: + print('No such index.') + continue + if suboperation == 'after': + a_cdllist.insert_after(ref_node, new_node) + elif suboperation == 'before': + a_cdllist.insert_before(ref_node, new_node) + + elif operation == 'remove': + index = int(do[1]) + node = a_cdllist.get_node(index) + if node is None: + print('No such index.') + continue + a_cdllist.remove(node) + + elif operation == 'quit': + break \ No newline at end of file diff --git a/data-structures/linked-lists/circularsinglelinkedlist.py b/data-structures/linked-lists/circularsinglelinkedlist.py new file mode 100644 index 0000000..1ef3c6e --- /dev/null +++ b/data-structures/linked-lists/circularsinglelinkedlist.py @@ -0,0 +1,116 @@ +class Node: + def __init__(self, data): + self.data = data + self.next = None + + +class CircularLinkedList: + def __init__(self): + self.head = None + + def get_node(self, index): + if self.head is None: + return None + current = self.head + for i in range(index): + current = current.next + if current == self.head: + return None + return current + + def get_prev_node(self, ref_node): + if self.head is None: + return None + current = self.head + while current.next != ref_node: + current = current.next + return current + + def insert_after(self, ref_node, new_node): + new_node.next = ref_node.next + ref_node.next = new_node + + def insert_before(self, ref_node, new_node): + prev_node = self.get_prev_node(ref_node) + self.insert_after(prev_node, new_node) + + def insert_at_end(self, new_node): + if self.head is None: + self.head = new_node + new_node.next = new_node + else: + self.insert_before(self.head, new_node) + + def insert_at_beg(self, new_node): + self.insert_at_end(new_node) + self.head = new_node + + def remove(self, node): + if self.head.next == self.head: + self.head = None + else: + prev_node = self.get_prev_node(node) + prev_node.next = node.next + if self.head == node: + self.head = node.next + + def display(self): + if self.head is None: + return + current = self.head + while True: + print(current.data, end = ' ') + current = current.next + if current == self.head: + break + + +a_cllist = CircularLinkedList() + +print('Menu') +print('insert after ') +print('insert before ') +print('insert at beg') +print('insert at end') +print('remove ') +print('quit') + +while True: + print('The list: ', end = '') + a_cllist.display() + print() + do = input('What would you like to do? ').split() + + operation = do[0].strip().lower() + + if operation == 'insert': + data = int(do[1]) + position = do[3].strip().lower() + new_node = Node(data) + suboperation = do[2].strip().lower() + if suboperation == 'at': + if position == 'beg': + a_cllist.insert_at_beg(new_node) + elif position == 'end': + a_cllist.insert_at_end(new_node) + else: + index = int(position) + ref_node = a_cllist.get_node(index) + if ref_node is None: + print('No such index.') + continue + if suboperation == 'after': + a_cllist.insert_after(ref_node, new_node) + elif suboperation == 'before': + a_cllist.insert_before(ref_node, new_node) + + elif operation == 'remove': + index = int(do[1]) + node = a_cllist.get_node(index) + if node is None: + print('No such index.') + continue + a_cllist.remove(node) + + elif operation == 'quit': + break \ No newline at end of file diff --git a/data-structures/linked-lists/is_palindrome.py b/data-structures/linked-lists/is_palindrome.py new file mode 100644 index 0000000..22c93ce --- /dev/null +++ b/data-structures/linked-lists/is_palindrome.py @@ -0,0 +1,72 @@ +def is_palindrome(head): + if not head: + return True + fast, slow = head.next, head + while fast and fast.next: + fast = fast.next.next + slow = slow.next + second = slow.next + node = None + while second: + nxt = second.next + second.next = node + node = second + second = nxt + while node: + if node.val != head.val: + return False + node = node.next + head = head.next + return True + + +def is_palindrome_stack(head): + if not head or not head.next: + return True + + # Get the midpoint + slow = fast = cur = head + while fast and fast.next: + fast, slow = fast.next.next, slow.next + + # Push the second half into the stack + stack = [slow.val] + while slow.next: + slow = slow.next + stack.append(slow.val) + + # Comparison + while stack: + if stack.pop() != cur.val: + return False + cur = cur.next + + return True + + +def is_palindrome_dict(head): + if not head or not head.next: + return True + d = {} + pos = 0 + while head: + if head.val in d.keys(): + d[head.val].append(pos) + else: + d[head.val] = [pos] + head = head.next + pos += 1 + checksum = pos - 1 + middle = 0 + for v in d.values(): + if len(v) % 2 != 0: + middle += 1 + else: + step = 0 + for i in range(0, len(v)): + if v[i] + v[len(v) - 1 - step] != checksum: + return False + step += 1 + if middle > 1: + return False + return True diff --git a/data-structures/linked-lists/singleLinkedModule.py b/data-structures/linked-lists/singleLinkedModule.py new file mode 100644 index 0000000..bda9418 --- /dev/null +++ b/data-structures/linked-lists/singleLinkedModule.py @@ -0,0 +1,97 @@ +# The program that creates a single link list of true values +# and implements the actions outlined in the link list. + +class LinkedList: + class ListNode: + def __init__(self, data, next= None): + self.info = data + self.next = next + + def getInfo(self): + return self.info + + def setInfo(self, value): + self.info = value + + def getNext(self): + return self.next + + def setNext(self, ptr): + self.next = ptr #end of listNode class + + def __init__(self): + self.head = None + self.last = None + self.size = 0 + + def __del__(self): + current = self.head + while current: + ptr = current + current = current.next + del ptr + + def getSize(self): + return self.size + def isEmpty(self): + return self.head == None + +#Search Node + + def searchNode(self, data): + if (self.isEmpty()): + return None + else: + ptr = self.head + found = False + while ptr and found is False: + if ptr.getInfo() == data: + found == True + else: + ptr == ptr.getNext() + return ptr + + def insertAtFirst(self, ptr): + self.head = ptr + self.size += 1 + if self.getSize() == 1: + self.last = self.head + return True + + def insertAfterNode(self, ptr): + if (self.isEmpty()): + self.head = self.last = ptr + else: + self.last.next = ptr + self.last = ptr + self.size += 1 + + def deleteNode(self, data): + current = self.head + pre = None + found = False + while current and found is False: + if current.getInfo() == data: + found = True + else: + pre = current + current = current.getNext() + if found: + if current == self.head: #first Node deleted + self.head = current.next + del current + else: + pre.next = current.next + current.next = None + del current #current = None + self.size -= 1 + return found + + def traverse(self): + if (self.isEmpty() != True): + ptr = self.head + while ptr: + print(ptr.info, end = "\n") + ptr = ptr.getNext() + + diff --git a/data-structures/zigzagtraversal_iterative.py b/data-structures/zigzagtraversal_iterative.py new file mode 100644 index 0000000..fa485b3 --- /dev/null +++ b/data-structures/zigzagtraversal_iterative.py @@ -0,0 +1,75 @@ +class Node: + """ + A Node has data variable and pointers to its left and right nodes. + """ + + def __init__(self, data): + self.left = None + self.right = None + self.data = data + +def make_tree() -> Node: + root = Node(1) + root.left = Node(2) + root.right = Node(3) + root.left.left = Node(4) + root.left.right = Node(5) + return root + +def zigzag_iterative(root: Node): + """ + ZigZag traverse by iterative method: Print node left to right and right to left, alternatively. + """ + if root == None: + return + + # two stacks to store alternate levels + s1 = [] # For levels to be printed from right to left + s2 = [] # For levels to be printed from left to right + + # append first level to first stack 's1' + s1.append(root) + + # Keep printing while any of the stacks has some nodes + while not len(s1) == 0 or not len(s2) == 0: + + # Print nodes of current level from s1 and append nodes of next level to s2 + while not len(s1) == 0: + temp = s1[-1] + s1.pop() + print(temp.data, end = " ") + + # Note that is left is appended before right + if temp.left: + s2.append(temp.left) + if temp.right: + s2.append(temp.right) + + # Print nodes of current level from s2 and append nodes of next level to s1 + while not len(s2) == 0: + temp = s2[-1] + s2.pop() + print(temp.data, end = " ") + + # Note that is rightt is appended before left + if temp.right: + s1.append(temp.right) + if temp.left: + s1.append(temp.left) + +def main(): # Main function for testing. + """ + Create binary tree. + """ + root = make_tree() + print("\nZigzag order traversal(iterative) is: ") + zigzag_iterative(root) + print() + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + main() +