-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
Updated singly_linked_list #2477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
cclauss
merged 15 commits into
TheAlgorithms:master
from
realDuYuanChao:singly_linked_list
Sep 25, 2020
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
dd60854
Updated singly_linked_list
realDuYuanChao e458450
fixup! Format Python code with psf/black push
1dbfc3b
undo __repr__
realDuYuanChao 61b4bb7
updating DIRECTORY.md
91d6f5c
UNTESTED CHANGES: Add an .__iter__() method.
cclauss 2f9f2b3
fixup! Format Python code with psf/black push
7a243b6
len(tuple(iter(self)))
cclauss 7cc7906
fixed __repr__()
realDuYuanChao 14fd3a7
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao d33b72f
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao b95f5a8
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao d9a95d8
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao 8d2296e
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao ba01f6c
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao 142ed15
Update data_structures/linked_list/singly_linked_list.py
realDuYuanChao File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,50 +9,110 @@ def __repr__(self): | |
|
||
class LinkedList: | ||
def __init__(self): | ||
self.head = None # initialize head to None | ||
self.head = None | ||
|
||
def __iter__(self): | ||
node = self.head | ||
while node: | ||
yield node.data | ||
node = node.next | ||
|
||
def __len__(self) -> int: | ||
""" | ||
Return length of linked list i.e. number of nodes | ||
>>> linked_list = LinkedList() | ||
>>> len(linked_list) | ||
0 | ||
>>> linked_list.insert_tail("head") | ||
>>> len(linked_list) | ||
1 | ||
>>> linked_list.insert_head("head") | ||
>>> len(linked_list) | ||
2 | ||
>>> _ = linked_list.delete_tail() | ||
>>> len(linked_list) | ||
1 | ||
>>> _ = linked_list.delete_head() | ||
>>> len(linked_list) | ||
0 | ||
""" | ||
return len(tuple(iter(self))) | ||
|
||
def __repr__(self): | ||
""" | ||
String representation/visualization of a Linked Lists | ||
""" | ||
return "->".join([str(item) for item in self]) | ||
|
||
def __getitem__(self, index): | ||
""" | ||
Indexing Support. Used to get a node at particular position | ||
""" | ||
if index < 0: | ||
raise ValueError("Negative indexes are not yet supported") | ||
for i, node in enumerate(self): | ||
if i == index: | ||
return node.data | ||
|
||
# Used to change the data of a particular node | ||
def __setitem__(self, index, data): | ||
current = self.head | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doctests needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean we need add doctests here ? |
||
# If list is empty | ||
if current is None: | ||
raise IndexError("The Linked List is empty") | ||
for i in range(index): | ||
if current.next is None: | ||
raise IndexError("list index out of range") | ||
current = current.next | ||
current.data = data | ||
|
||
def insert_tail(self, data) -> None: | ||
self.insert_nth(len(self), data) | ||
|
||
def insert_head(self, data) -> None: | ||
self.insert_nth(0, data) | ||
|
||
def insert_nth(self, index: int, data) -> None: | ||
if not 0 <= index <= len(self): | ||
raise IndexError("list index out of range") | ||
new_node = Node(data) | ||
if self.head is None: | ||
self.insert_head(data) # if this is first node, call insert_head | ||
self.head = new_node | ||
elif index == 0: | ||
new_node.next = self.head # link new_node to head | ||
self.head = new_node | ||
else: | ||
temp = self.head | ||
while temp.next: # traverse to last node | ||
for _ in range(index - 1): | ||
temp = temp.next | ||
temp.next = Node(data) # create node & link to tail | ||
|
||
def insert_head(self, data) -> None: | ||
new_node = Node(data) # create a new node | ||
if self.head: | ||
new_node.next = self.head # link new_node to head | ||
self.head = new_node # make NewNode as head | ||
new_node.next = temp.next | ||
temp.next = new_node | ||
|
||
def print_list(self) -> None: # print every node data | ||
temp = self.head | ||
while temp: | ||
print(temp.data) | ||
temp = temp.next | ||
|
||
def delete_head(self): # delete from head | ||
temp = self.head | ||
if self.head: | ||
self.head = self.head.next | ||
temp.next = None | ||
return temp | ||
print(self) | ||
|
||
def delete_head(self): | ||
return self.delete_nth(0) | ||
|
||
def delete_tail(self): # delete from tail | ||
temp = self.head | ||
if self.head: | ||
if self.head.next is None: # if head is the only Node in the Linked List | ||
self.head = None | ||
else: | ||
while temp.next.next: # find the 2nd last element | ||
temp = temp.next | ||
# (2nd last element).next = None and temp = last element | ||
temp.next, temp = None, temp.next | ||
return temp | ||
return self.delete_nth(len(self) - 1) | ||
|
||
def delete_nth(self, index: int = 0): | ||
if not 0 <= index <= len(self) - 1: # test if index is valid | ||
raise IndexError("list index out of range") | ||
delete_node = self.head # default first node | ||
if index == 0: | ||
self.head = self.head.next | ||
else: | ||
temp = self.head | ||
for _ in range(index - 1): | ||
temp = temp.next | ||
delete_node = temp.next | ||
temp.next = temp.next.next | ||
return delete_node.data | ||
|
||
def is_empty(self) -> bool: | ||
return self.head is None # return True if head is none | ||
return self.head is None | ||
|
||
def reverse(self): | ||
prev = None | ||
|
@@ -70,101 +130,74 @@ def reverse(self): | |
# Return prev in order to put the head at the end | ||
self.head = prev | ||
|
||
def __repr__(self): # String representation/visualization of a Linked Lists | ||
current = self.head | ||
string_repr = "" | ||
while current: | ||
string_repr += f"{current} --> " | ||
current = current.next | ||
# END represents end of the LinkedList | ||
return string_repr + "END" | ||
|
||
# Indexing Support. Used to get a node at particular position | ||
def __getitem__(self, index): | ||
current = self.head | ||
def test_singly_linked_list() -> None: | ||
""" | ||
>>> test_singly_linked_list() | ||
""" | ||
linked_list = LinkedList() | ||
assert linked_list.is_empty() is True | ||
assert str(linked_list) == "" | ||
|
||
# If LinkedList is empty | ||
if current is None: | ||
raise IndexError("The Linked List is empty") | ||
try: | ||
linked_list.delete_head() | ||
assert False # This should not happen. | ||
except IndexError: | ||
assert True # This should happen. | ||
|
||
# Move Forward 'index' times | ||
for _ in range(index): | ||
# If the LinkedList ends before reaching specified node | ||
if current.next is None: | ||
raise IndexError("Index out of range.") | ||
current = current.next | ||
return current | ||
try: | ||
linked_list.delete_tail() | ||
assert False # This should not happen. | ||
except IndexError: | ||
assert True # This should happen. | ||
|
||
# Used to change the data of a particular node | ||
def __setitem__(self, index, data): | ||
current = self.head | ||
# If list is empty | ||
if current is None: | ||
raise IndexError("The Linked List is empty") | ||
for i in range(index): | ||
if current.next is None: | ||
raise IndexError("Index out of range.") | ||
current = current.next | ||
current.data = data | ||
for i in range(10): | ||
assert len(linked_list) == i | ||
linked_list.insert_nth(i, i + 1) | ||
assert str(linked_list) == "->".join(str(i) for i in range(1, 11)) | ||
|
||
def __len__(self): | ||
""" | ||
Return length of linked list i.e. number of nodes | ||
>>> linked_list = LinkedList() | ||
>>> len(linked_list) | ||
0 | ||
>>> linked_list.insert_tail("head") | ||
>>> len(linked_list) | ||
1 | ||
>>> linked_list.insert_head("head") | ||
>>> len(linked_list) | ||
2 | ||
>>> _ = linked_list.delete_tail() | ||
>>> len(linked_list) | ||
1 | ||
>>> _ = linked_list.delete_head() | ||
>>> len(linked_list) | ||
0 | ||
""" | ||
if not self.head: | ||
return 0 | ||
linked_list.insert_head(0) | ||
linked_list.insert_tail(11) | ||
assert str(linked_list) == "->".join(str(i) for i in range(0, 12)) | ||
|
||
count = 0 | ||
cur_node = self.head | ||
while cur_node.next: | ||
count += 1 | ||
cur_node = cur_node.next | ||
return count + 1 | ||
assert linked_list.delete_head() == 0 | ||
assert linked_list.delete_nth(9) == 10 | ||
assert linked_list.delete_tail() == 11 | ||
assert str(linked_list) == "->".join(str(i) for i in range(1, 10)) | ||
|
||
|
||
def main(): | ||
A = LinkedList() | ||
A.insert_head(input("Inserting 1st at head ").strip()) | ||
A.insert_head(input("Inserting 2nd at head ").strip()) | ||
from doctest import testmod | ||
|
||
testmod() | ||
|
||
linked_list = LinkedList() | ||
linked_list.insert_head(input("Inserting 1st at head ").strip()) | ||
linked_list.insert_head(input("Inserting 2nd at head ").strip()) | ||
print("\nPrint list:") | ||
A.print_list() | ||
A.insert_tail(input("\nInserting 1st at tail ").strip()) | ||
A.insert_tail(input("Inserting 2nd at tail ").strip()) | ||
linked_list.print_list() | ||
linked_list.insert_tail(input("\nInserting 1st at tail ").strip()) | ||
linked_list.insert_tail(input("Inserting 2nd at tail ").strip()) | ||
print("\nPrint list:") | ||
A.print_list() | ||
linked_list.print_list() | ||
print("\nDelete head") | ||
A.delete_head() | ||
linked_list.delete_head() | ||
print("Delete tail") | ||
A.delete_tail() | ||
linked_list.delete_tail() | ||
print("\nPrint list:") | ||
A.print_list() | ||
linked_list.print_list() | ||
print("\nReverse linked list") | ||
A.reverse() | ||
linked_list.reverse() | ||
print("\nPrint list:") | ||
A.print_list() | ||
linked_list.print_list() | ||
print("\nString representation of linked list:") | ||
print(A) | ||
print(linked_list) | ||
print("\nReading/changing Node data using indexing:") | ||
print(f"Element at Position 1: {A[1]}") | ||
A[1] = input("Enter New Value: ").strip() | ||
print(f"Element at Position 1: {linked_list[1]}") | ||
linked_list[1] = input("Enter New Value: ").strip() | ||
print("New list:") | ||
print(A) | ||
print(f"length of A is : {len(A)}") | ||
print(linked_list) | ||
print(f"length of linked_list is : {len(linked_list)}") | ||
|
||
|
||
if __name__ == "__main__": | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doctests needed?