Data Structure and Algorithms (005) Fall 2024 - Week 4
Data Structure and Algorithms (005) Fall 2024 - Week 4
Fall 2024
Instructor: Prof. John Yun
Lecture: 9-12P, Wednesdays; S2-402
Week 4
Fall 2024
List
• Data arranged in a line or Data lined up.
ADT (Abstract Data Type)
• List of tasks that represents the type of data
being processed
10 35 40 17 95 50 48 33 9
10 17 35 40 55
• List
• Array List (Python Built-in List)
• Linked List
• Array List vs. Linked List
• Improvement and
Expansion for Linked List
Array List
(Python Built-in List)
Week 4
Fall 2024
List (array list) Object Structure
insert(i, x) Insert element x into ith position
insert(3,77)
a[ ] 10 35 40 17 95 50 48 33 9
First
0번 Element
원소 8th번element
원소 len(a): 9
insert(0, 77)
a[0] a[9]
a[ ] 77 10 35 40 17 95 50 48 33 9
First
0번 원소 Element 8th9번
element
원소 len(a): 10
Example of the Best Insertion Efficiency
a[8]
a[ ] 10 35 40 17 95 50 48 33 9
8th
8번 element
원소 len(a): 9
append(77)
a[9]
a[ ] 10 35 40 17 95 50 48 33 9 77
99th번element
원소 len(a): 10
Delete
a[ ] 10 35 40 17 95 50 48 33 9
33rd번element
원소 8th 8element
번 원소 len(a): 9
a[ ] 10 35 40 17 95 50 48 33
3rd3번
element len(a): 8
원소 7th7element
번 원소
How to use the method
Element Insertion
Element Deletion
How to use the method
Other Tasks
Limitation of Python Built-in List
• Underneath is implemented as an array
• Disadvantages of arrays
• Since elements are stored in contiguous space, insertions and deletions require
shifting operations.
• Since the size must be predetermined, an overflow requires reallocating the array
and copying the contents.
• But, in Python, it is managed automatically, so users don't need to worry
about it.
Week 4
Fall 2024
Linked List Object Structure
…
Node object Node object Node object
Linked List
item next
class ListNode:
def __init__(self, newItem, nextNode:'ListNode'):
self.item = newItem
self.next = nextNode
Node Class
Usage Example of ListNode Class
Head Node
• Linked Lists usually contains the reference(i.e. head) to
the first node None
10 17 35 40
head item next item next item next item next
Insertion
10 17 35 40 55
25
Deletion
10 17 25 35 40 55
Typical Form
Representative Form
10 17 35 40 55
head
Initial State
10 17 35 40 55
25
head prev
newNode
newNode.item ← x prev
newNode.next ← prev.next
prev.next ← newNode …
_ _numItems += 1
x
newNode
x
newNode
head
Initial State
dummy head
head
Insert(): The version with a dummy head
Example of inserting element at the front of the linked list with the
dummy head
Inserting an element into a linked list (with Dummy Head) If there is a dummy head,
all insertions will satisfy
because prev always exists.
append()
Inserting element x at the end
Deleting a node in the middle: Okay Deleting the node at the end: Okay
Example of deleting the element 35 from the linked list Example of deleting an element at the end
head
Deleting the element x from a linked list (with dummy head) If you have the dummy head,
this is enough because prev
always exists
Miscellaneous Tasks
Informs if the list is empty
dummy head
3 examples of deleting element from the linked list with the dummy head
def remove(self, x): def __findNode(self, i:int) -> (ListNode, ListNode):
(prev, curr) = self.__findNode(x) prev = self.__head # dummy head
if curr != None: curr = prev.next # 0번 노드
Node #0
prev.next = curr.next while curr != None:
self.__numItems -= 1 if curr.item == x:
return x return (prev, curr)
else: else:
return None prev = curr; curr = curr.next
return (None, None)
def reverse(self):
a = LinkedListBasic()
for index in range(self.__numItems):
a.insert(0, self.get(index))
self.clear()
for index in range(a.size()):
self.append(a.get(index))
def printList(self):
curr = self.__head.next # 0번 노드
Node #0:: 더미 헤드the
Node after 다음 노드head
dummy
while curr != None:
print(curr.item, end=" ")
curr = curr.next
print()
• List
• Array List (Python Built-in List)
• Linked List
• Array List vs. Linked List
• Improvement and
Array List Expansion for Linked List
vs.
Linked List
Week 4
Fall 2024
Array List
• Intuitively Name
• If an index is given, it can be accessed immediately (in constant time)
• Stored in contiguous space, so shifting operations are required for insertion or deletion.
• Since the size must be predetermined, in the case of overflow, the array needs to be
reallocated and the contents copied.
• Efficiency decreases with larger arrays.
3rd element
3rd element 8th element
insert(i) Location Access Θ(1), Insert Task O(n) Location Access O(n), Insert Task Θ(1)
pop(i) Location Access Θ(1), Delete Task O(n) Location Access O(n), Delete Task Θ(1)
remove(x) Element Find O(n), Delete Task O(n) Element Find O(n), Delete Task Θ(1)
Week 4
Fall 2024
Improvement 1: Circular Linked List
• Linking next to the first node instead of ending with null
value
• The accessibility difference between the front and the
back has been eliminated
Inserting an element at the end of the Circular Linked List which has
the dummy head
Improvement 2: Variable Parameter
• Reminder: pop(i) always required the position of the
element to be deleted
• Improvement: Position no longer needed
pop(i): delete element in the
ith position
pop(): delete last element
pop(-1): delete last element
Improvement 2: Variable Parameter
def pop(self, *args):
# 가변 This 파라미터
is to process. 인자가 없거나when
the last element -1이면 there마지막 원소로 or
is no parameter, 처리하기
arguments, or if.it’s 1.
위함
Satisfies
# 파이썬 리스트 규칙 만족the Python List rule
if self.isEmpty():
return None
# 인덱스 i 결정
Determines index i
if len(args) != 0: # pop(k)
Assign과 i=k같이 인자가
if there 있으면like
is an argument i=kpop(k)
할당
i = args[0]
if len(args) == 0 or i == -1: # pop() 에i 인자가
Assign elementpop(-1)
to the last없거나 if there is이면 i에 맨 끝
no argument 인덱스
in pop() 할당
or pop(-1)
i = self.__numItems - 1
# i번 원소ith삭제
Delete . 이후는
element. 앞절의
Following codepop(i) 와 같음
is the same . preceding pop(i)
as the
if (i >= 0 and i <= self.__numItems - 1):
prev = self.getNode(i - 1)
retItem = prev.next.item
prev.next = prev.next.next
if i == self.__numItems - 1:
self.__tail = prev
self.__numItems -= 1
return retItem
else:
return None
Improvement 3: Iteration
• Representative Design Pattern
• Allows easy traversal of the elements in an object.
Usage Example
def printList(self):
for element in self:
print(element, end=' ')
print()
Complete Code: Circular Linked List
from DS.list.listNode import ListNode
class CircularLinkedList:
def __init__(self):
self.__tail = ListNode("dummy", None)
self.__tail.next = self.__tail
self.__numItems = 0
head
head
Node Structdure
class BidirectNode:
def __init__(self, newItem, prevNode:'BidirectNode', nextNode:'BidirectNode'):
self.item = newItem
self.prev = prevNode
self.next = nextNode
Doubly Linked List with the dummy head
newNode ← BidirectNode(newItem, prev, prev.next)
newNode.next.prev ← newNode
Insert prev.next ← newNode
numItems++
curr.prev.next ← curr.next
Delete curr.next.prev ← curr.prev
numItems--
10 35 40 55
dummy head
10 35 40 55
head prev
dummy head
10 35 40 55
38
head prev
Example of inserting an element to a Circular Linked List newNode
Confirmation: This is OKAY for inserting an element in the front.
newNode ← BidirectNode(newItem, prev, prev.next)
newNode.next.prev ← newNode
prev.next ← newNode
numItems++
head head
prev prev
Delete
curr.prev.next ← curr.next
curr.next.prev ← curr.prev
numItems--
17 35 40
CurrNode
Confirmation: When deleting an element at the front, this is OKAY
curr.prev.next ← curr.next
curr.next.prev ← curr.prev
numItems--
class CircularDoublyLinkedList:
def __init__(self):
self.__head = BidirectNode("dummy", None)
self.__head.prev = self.__head
self.__head.next = self.__head
self.__numItems = 0
def clear(self):
self.__head = BidirectNode("dummy", None, None)
self.__head.prev = self.__head
self.__head.next = self.__head 3/5
self.__numItems = 0
def count(self, x) -> int:
Same as … class CircularLinkedList …
a is순환가능한
def extend(self, a): # a는 all objects that모든
are traversable
객체
Same as … class CircularLinkedList…