Python data structure and algorithm -- basic data structure

Basic data structure

1. Linear structure

  1. Definition of linear structure: linear structure is a set of ordered data items, in which each data item has a unique precursor and successor
    Except for the first one, there is no precursor, and the last one has no successor
    When a new data item is added to the data set, it will only be added to the data set with this property before or after the original data item, which is called linear structure

  2. Linear structure always has two ends. In different cases, the names of the two ends are also different
    Left and right ends, front and rear ends, top and bottom ends

  3. The address at both ends is not the key. The key difference between different linear structures lies in the way data items are increased or decreased (some structures only allow data items to be added from one end, while others allow data items to be removed from both ends)

  4. The four simplest but powerful structures: Stack, Queue, Deque and List
    What these data sets have in common is that there is only a sequential relationship between data items, which is a linear structure

1. Stack abstract data type and Python implementation

  1. Stack: an ordered collection of data items. In the stack, the addition and removal of data items occur only at the same end. This end is called the "top" of the stack, and the other end is called the "bottom base" of the stack
  2. Stack: last in first out (LIFO). The closer the data item is to the bottom of the stack, the longer it will stay in the stack
  3. Stack characteristics: reverse order
The order of entering and leaving the stack is exactly the opposite
 We have encountered this feature of reverse access order in some computer operations
    Browser Back back"Button, first back Is the most recently visited web page Word Yes“ Undo" Button. The most recent operation is cancelled first
  1. Stack operation in python
Stack(): Create an empty stack without any data items
push(item): take item Added to the top of the stack, no return value
pop(): The data item at the top of the stack is removed and returned, and the stack is modified
peek():  " Peep "stack top data item, return the data item at the top of the stack but do not remove it, and the stack will not be modified
isEmpty(): Returns whether the stack is empty
size(): Returns how many data items are in the stack

Implementing ADT Stack with Python

class Stack:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def push(self, item):
        self.items.append(0, item)
    def pop(self):
        return self.items. pop(0)
    def peek(self):
        return self.items[0]
    def size(self) :
        return len(self.items )

Another implementation of ADT Stack
❖ different implementation schemes maintain the stability of ADT interface, but the performance is different. The complexity of push/pop is O(n) for the version at the top and end of the stack (upper), while the complexity of push/pop is O(1) for the implementation at the top and end of the stack (lower)

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 )
  1. Application of stack
  • Simple bracket matching
    Scan the bracket string from left to right. The newly opened left bracket should match the first encountered right bracket. In this way, the first left bracket (first opened) should match the last right bracket (last encountered). This identification of reverse order is just in line with the characteristics of the stack
  • Convert decimal to binary
    Binary conversion adopts the "divide by 2 for remainder" algorithm. Divide integers by 2 continuously, and the remainder obtained each time is the binary bits from low to high. In the "divide by 2" process, the remainder obtained is in the order from low to high, while the output is from high to low, so a stack is required to reverse the order

2. Queue abstract data type and Python implementation

  • Queue is an ordered data set, which is characterized in that the addition of new data items always occurs at one end (usually referred to as the "tail rear" end) and the removal of existing data items always occurs at the other end (usually referred to as the "front" end)
    When the data item is added to the queue, it first appears at the end of the queue. With the removal of the data item at the head of the queue, it gradually approaches the head of the queue
  • The principle of this order arrangement is called (FIFO: first in first out) first in first out or "first come first served"
  • The abstract data type Queue is defined by the following operations:
Queue(): Create an empty queue object with a return value of Queue Object;
enqueue(item): Add data item item Added to the end of the queue, no return value;
dequeue(): Remove the data item from the queue head, the return value is the queue head data item, and the queue is modified;
isEmpty(): Test whether the queue is empty, and the return value is Boolean
size(): Returns the number of data items in the queue.

Python implements ADT Queue

# List is used to hold the data items of the Queue
# Take the first end of the List as the end of the queue, and the end of the List as the first end of the queue
# enqueue() complexity is O(n),dequeue() complexity is O(1)
#The complexity of the implementation is reversed

class Queue:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def enqueue(self, item):
        self.items.insert(0,item)

    def dequeue(self):
        return self.items.pop()

    def size(self):
        return len(self.items)

3. Double ended queue abstract data type and Python implementation

  • Deque is an ordered data set, which is similar to a queue. Its two ends can be called "head" and "tail", but data items in deque can be added from the head of the queue or from the tail of the queue; data items can also be removed from both ends. In a sense, deque integrates the capabilities of stack and queue
  • However, double ended queues do not have inherent LIFO or FIFO characteristics
  • deque defined actions
Deque(): Create an empty double ended queue
addFront(item): take item Join the team leader
addRear(item): take item Join the tail of the team
removeFront(): Remove the data item from the queue leader, and the return value is the removed data item
removeRear(): Remove the data item from the end of the queue, and the return value is the removed data item
isEmpty(): return deque Is it empty
size(): return deque Number of data items contained in

Python implements ADT Deque

class Deque:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def addFront(self, item):
        self.items.append(item)

    def addRear(self, item):
        self.items.insert(0,item)

    def removeFront(self):
        return self.items.pop()

    def removeRear(self):
        return self.items.pop(0)

    def size(self):
        return len(self.items)

4. List

  • A dset in which data items are stored in relative positions

1. Abstract data type: unordered table List

  • Operation of unordered List
List(): Create an empty list
add(item): Add a data item to the list, assuming item It didn't exist in the list
remove(item): Remove from list item,The list has been modified, item It should have existed in the table
search(item): Find in list item,Returns a Boolean value
isEmpty(): Returns whether the list is empty
size(): Returns how many data items the list contains
append(item): Add a data item to the end of the table, assuming item It didn't exist in the list
index(item): Returns the position of the data item in the table
insert(pos,item): Insert data item into location pos,hypothesis item It didn't exist in the list,
                At the same time, the original list has enough data items to make item Occupy position pos
pop(): Remove data items from the end of the list, assuming that the original list has at least 1 data item
pop(pos): Remove at pos Assuming that the original list exists pos

2. Use linked list to realize unordered list

  • In order to realize the data structure of unordered table, the scheme of linked table can be adopted.
  • Although the list data structure requires to maintain the front and rear relative positions of data items, the maintenance of this front and rear position does not require the data items to be stored in a continuous storage space in turn
  • The most basic element of the linked list implementation is the Node. Each Node must contain at least two information: the data item itself and the reference information pointing to the next Node
    Note that there is no next node when next is None, which is very important
  • Linked list implementation: Node
class Node:
    def __init__(self,initdata):
        self.data = initdata
        self.next = None

    def getData(self):
        return  self.data

    def getNext(self):
        return self.next

    def setData(self,newdata):
        self.data = newdata

    def setNext(self,newnext):
        self.next = newnext
        
# You can link nodes to build data sets to implement unordered tables
"""The first and last nodes of the linked list are the most important if you want to access the linked list
    All nodes must be traversed along the link from the first node"""
"""Therefore, the unordered table must have reference information to the first node
 Set up a property head,Save a reference to an empty table for the first node head by None"""
class UnorderedList:
    def __init__(self):
        self.head = None
#With the addition of data items, the head of the unordered table always points to the first node in the chain
"""Unordered table mylist The object itself does not contain data items
(Data item (in node)
Which contains head Only for the first node Node Reference to"""


# Implementation of isEmpty add size search remove method
class UnorderedList:
    def __init__(self):
        self.head = None
    def isEmpty(self):
        return  self.head == None
    def add(self,item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head =temp
    def size(self):
        current = self.head
        count = 0
        while current != None
            count = count + 1;
            current = current.getNext()
        return  count
    def search(self,item):
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        return  found
    
    def remove(self,item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
            if previous == None:
                self.head = current.getNext()
            else:
                previous.setNext(current.getNext())

3. Abstract data type: ordered table OrderedList

  • An ordered table is a data item whose position in the list is determined according to its comparable properties (such as integer size and alphabet order)
  • The smaller the data item, the closer it is to the head of the list, and the closer it is to the front
  • Operations defined by OrderedList
OrderedList(): Create an empty ordered table
add(item): Add a data item to the table and keep the overall order. This item did not exist
remove(item): Remove a data item from the ordered table. This item should exist and the ordered table is modified
search(item): Find the data item in the ordered table and return whether it exists
isEmpty(): Empty table
size(): Returns the number of data items in the table index(item): Returns the position of the data item in the table. This item should exist
pop(): Remove and return the last item in the ordered table. There should be at least one item in the table
pop(pos): Remove and return the data item at the specified location in the ordered table, which should exist
  • Implementation of ordered table OrderedList
# It is also realized by linked list method
# Node definitions are the same
# OrderedList also sets a head to save the reference to the header of the linked list
"""about isEmpty/size/remove These methods have nothing to do with the order of nodes, so their implementation is consistent with UnorderedList It's the same.
search/add Methods need to be modified"""
class Node:
    def __init__(self,initdata):
        self.data = initdata
        self.next = None

    def getData(self):
        return  self.data

    def getNext(self):
        return self.next

    def setData(self,newdata):
        self.data = newdata

    def setNext(self,newnext):
        self.next = newnext
        
class orderedList:
    def __init__(self):
        self.head = None

    def add(self,item):
        current = self.head
        previous = None
        stop = False
        while current != None and not  stop:
            if current.getData() > item:
                stop = True
            else: 
                previous = current
                current = current.getNext()
            
            temp = Node(item)
            if previous == None:
                temp.setNext(self.head)
                self.head = temp
            else:
                temp.setNext(current)
                previous.setNext(temp)
    def size(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1;
            current = current.getNext()
        return  count
    def search(self,item):
        current = self.head
        found = False
        stop = False
        while current != None and not found and not stop:
            if current.getData() == item:
                found = True
            else:
                if current.getData() > item:
                    stop = True
                else:
                    current = current.getNext
        return found

    def remove(self,item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()
            if previous == None:
                self.head = current.getNext()
            else:
                previous.setNext(current.getNext())

4. Algorithm analysis of linked list implementation

  • The analysis of the complexity of the linked list mainly depends on whether the corresponding method involves the traversal of the linked list
  • For a linked list with n nodes
    isEmpty is O(1), because you only need to check whether the head is None
    size is O(n), because there is no other way to know the number of nodes except to traverse to the end of the table
    search/remove and the add method of the ordered table are O(n), because it involves the traversal of the linked list. According to the probability, the average number of operations is n/2
    The add method of the unordered table is O(1), because it only needs to be inserted into the header
  • The List implemented by the linked List has different time complexity from the List data type built in Python in the implementation of some of the same methods
  • This is mainly because Python's built-in list data type is implemented based on sequential storage and optimized

Keywords: Python Algorithm data structure

Added by kmaid on Mon, 18 Oct 2021 09:09:57 +0300