Actually my sort algorithm works, but there is a problem.
I have a class namely SortedItem which includes
def __init__(self, point, cost):
self.coordinate = point
self.cost = cost
and I have also priority queue which sorts the this SortedItem by its cost:
class PriorityQueue:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def sortComparatorByCost(self, item):
return item.cost
def enqueue(self, item):
self.items.append(item)
self.items.sort(key=self.sortComparatorByCost, reverse=True)
def dequeue(self):
return self.items.pop()
def returnQueueAsString(self):
queue_str = ""
for eachItem in self.items:
queue_str += str(eachItem) + " "
return queue_str
def isQueueContainsElement(self, element):
for eachElement in self.items:
if eachElement[0] == element:
return True
return False
The problem occurs here:
- I have defined some order to add queue. Let's say I am adding this objects to the queue:
obj1 = SortedItem((1,0), 10))
queue.enqueue(obj1)
obj2 = SortedItem((2,0), 15))
queue.enqueue(obj2)
obj3 = SortedItem((2,1), 15))
queue.enqueue(obj3)
Now I have to get objects from queue in this order (obj1, obj2, obj3).
However python built-in sort function sort these objects like this: (obj1, obj3, obj2) (because obj2 and obj3 has the same cost)
How can i solve this issue. I mean If 2 objects cost is the same, I should get the first added one.
Note that: I have just created a simple example of my problem. If you try this code you may get the objects in this order: obj1, obj2, obj3
Instead of sorting the items in reverse order and removing them from the right,
def enqueue(self, item):
self.items.append(item)
self.items.sort(key=self.sortComparatorByCost, reverse=True)
def dequeue(self):
return self.items.pop()
you could remove them from the left. That would avoid reversing the order of insertion of the items with the same cost.
def enqueue(self, item):
self.items.append(item)
self.items.sort(key=self.sortComparatorByCost)
def dequeue(self):
return self.items.pop(0)
Removing items from the beginning of a list is not efficient, however, so you could better use a deque (replacing pop(0) by popleft()) to fix that. A deque on the other hand, has no in-place sort() method, so would need to replace self.items.sort() by self.items = deque(sorted(self.items)) as well.
Related
I am currently learning DS in python. I was creating class for stack.
I had couple of questions-
What type of coding skills is required for me to be an expert in Data Structures in python? Is it using the in-built structures of python or creating the basic data structures like stack, queue, linked lists, graphs etc.?
How can I check whether the elements of a list are integer or not so that I can pop them?
class Stack():
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
def show(self):
return self.items
lt = ['a', '1', '2', 'b', '3']
a = Stack()
for i in lt:
a.push(i)
for j in lt:
if not j.isdigit():
a.pop()
a.show()
how can I use the if statement here so that all the non-integer items can be popped from the list?
the if j!=%d is throwing an error
You don't need to pop from a, since you didn't add anything to it. Here's how you'd write that as a loop:
lst = ['a','1','2','b','3']
a = []
for i in lst:
if not i.isdigit():
a.push(i)
Better is the list comprehension I cited in the comments:
lst = ['a','1','2','b','3']
a = [i for i in lst if not i.isdigit()]
Note that you should not name your own variables list, since that hides the Python built-in type.
Answer Question No 1:
in-built structures of python is not a solution to understand data structure. so if you want really improve your skill on data structure and algorithm then defiantly do it manually. and under stand core concept how stack, link list, queue different type of sorting works. after clear concept understand BFS , DFS, shortest path find out algorithm and also different type of algorithm. You will achieved the knowledge about time complexity and space complexity of algorithm. so don't go built in structure if you have know idea about data structure and algorithm.
Answer Question No 2:
class Stack():
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
def show(self):
return self.items
lt = ['a', '1', '2', 'b', '3']
a = Stack()
for j in lt:
if not j.isdigit():
a.push(j)
a.show()
I don't understand the difference between just using a list and appending and popping from it or creating a class which does the same thing?
list = []
list.append(1)
list.append(2)
class myStack:
def __init__(self):
self.container = [] # You don't want to assign [] to self - when you do that, you're just assigning to a new local variable called `self`. You want your stack to *have* a list, not *be* a list.
def isEmpty(self):
return self.size() == 0 # While there's nothing wrong with self.container == [], there is a builtin function for that purpose, so we may as well use it. And while we're at it, it's often nice to use your own internal functions, so behavior is more consistent.
def push(self, item):
self.container.append(item) # appending to the *container*, not the instance itself.
def pop(self):
return self.container.pop() # pop from the container, this was fixed from the old version which was wrong
def peek(self):
if self.isEmpty():
raise Exception("Stack empty!")
return self.container[-1] # View element at top of the stack
def size(self):
return len(self.container) # length of the container
def show(self):
return self.container # display the entire stack as list
s = myStack()
s.push('1')
s.push('2')
It looks the same to me so wouldn't the first code be a better implementation of a stack?
I'm doing some basic Python programming practice exercises and tried to implement a queue (using lists). Unfortunately, I'm getting behavior for my isempty() function that I don't understand. When running the code below, the last two lines give different answers: A yields False, while B yields True. Why doesn't A also yield False?
class Queue:
def __init__(self):
self.items = []
def push(self,item):
self.items.insert(0,item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
def isempty(self):
return self.size == 0
q = Queue()
q.push("a")
q.push("b")
print(q.pop())
print(q.isempty())
print(q.pop())
print(q.isempty()) # shouldn't this (A)...
print(q.size()==0) # ...and this (B) yield the same answer?
Just change your isempty() method to:
def isempty(self):
return self.size() == 0
Your implementation of Queue.isempty() is checking to see if the method size is equal to the integer 0, which will never be true.
class Queue:
def __init__(self):
self.items = []
def push(self,item):
self.items.insert(0,item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
def isempty(self):
return self.size == 0
q = Queue()
print(q.size)
Produces:
<bound method Queue.size of <__main__.Queue object at 0x02F4EA10>>
The easiest solution is to use Christopher Shroba's suggestion to modify your Queue.isempty() implementation to use the list's size method.
I am writing a Python module in which two threads access one list. One thread adds 500 items to the list per second, and the other thread reads the list at an irregular interval. I want to make a thread-safe "list" class to avoid having to use locks every time I read or write to the list (suggested by this answer to a previous question on SO).
Here is my first go at a thread-safe list class (with help from these previous SO answers: 1 and 2). Are there any methods that should be locked that are not currently locked, or any methods that do not require a lock that are currently locked?
import collections
import threading
class ThreadSafeList(collections.MutableSequence):
"""Thread-safe list class."""
def __init__(self, iterable=None):
if iterable is None:
self._list = list()
else:
self._list = list(iterable)
self.rlock = threading.RLock()
def __len__(self): return len(self._list)
def __str__(self): return self.__repr__()
def __repr__(self): return "{}".format(self._list)
def __getitem__(self, i): return self._list[i]
def __setitem__(self, index, value):
with self.rlock:
self._list[index] = value
def __delitem__(self, i):
with self.rlock:
del self._list[i]
def __iter__(self):
with self.rlock:
for elem in self._list:
yield elem
def insert(self, index, value):
with self.rlock:
self._list.insert(index, value)
Ok so im trying to input a word in a stack and I want to print all of them after I input a string. So I can only print them one at a time. I tried using a for loop outside but Stacks are apparently not iterable. So I iterating it inside the stack. It still is not working.
class Stack:
def __init__(self):
self.items = []
def push(self,items):
self.items.insert(0,items)
def pop(self):
for x in self.items:
print( self.items.pop(0))
def show(self):
print (self.items)
s = Stack()
s.show()
placed = input("enter")
item = s.pop()
print(item, "is on top", s)
Give your Stack class a __len__ method, this will make testing if the stack is empty easier:
class Stack:
def __init__(self):
self.items = []
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()
def show(self):
print (self.items)
def __len__(self):
return len(self.items)
stack = Stack()
stack.push('World!')
stack.push('Hello')
while stack: # tests the length through __len__
print(stack.pop())
Note that I simply .append() to the end of the .items list, then later on .pop() (no arguments) again, removing from the end of the list.
To make your class an iterable type, you'd need to add at least an __iter__ method, optionally together with a .__next__() method:
class Stack:
# rest elided
def __iter__(self):
return self
def next(self):
try:
return self.items.pop()
except IndexError: # empty
raise StopIteration # signal iterator is done