python data structure - linear form

Linear table

线性表可以看作是一种线性结构(可以分为顺序线性结构,离散线性结构)

Table 1. Linear Type:

  1. Order table

    元素存储在一大块连续存储的地址中,首元素存入存储区的起始位置,其余元素顺序存放。
    
    (元素之间的逻辑关系与物理地址上相邻的关系相同)
  2. Linked table:

    将表元素存放在通过链接构造的一系列存储块中
    (元素的物理位置不相邻)

2. The order of the table to achieve

  • Order to achieve the table

    Ideas:

$$
Loc (e_i) = Loc (E_0) + I c *
$$
wherein c is an element of the storage space required, i.e., size

Built-in elements: The following diagram left external elements: the lower-right

  1. Built-elements:

Shall ensure that each memory cell of the same size, i.e., of the same type

  1. External elements:

Stored essentially real address storage element (ie external elements, by the address stored in the element in order to find the element), may store data such as those containing a plurality of types of data objects may be iterative lists (different types of storage , occupied by the size of your memory is not the same)

补充:
    int类型 数据在内存中占4个字结(byte,32位)
    char类型数据在内存中占1个字结
    内存中从下为0开始计数,反人类的设计,本质上是记录的偏移量    
  • The structure of sequence table: contains header information, two of the data area

  • Header information: the order table capacity, it has stored the current number of elements

  • Data area: a data area following the header with the relationship of FIG.

    Integral: FIG left split: the right in FIG.

    1. 分离式:便于顺序表的扩充,本质上是将原有第二段分表复制到一块内存区更大分表中,然后释放这个小的分表(通常使用分离式)
    2. 一体式:顺序表的扩充本质上是复制到更大的内存块中,表头地址改变
  • Expansion of the elements of the storage area strategic issues (reservation mechanism)

    • Every expansion to increase the number of fixed storage (space-saving knot)
    • Double extension method, every time the expansion is twice or n times (space for time)

3. The realization of the list

  • List (linked table) implementation
特点:
    1. 离散的进行存储,每次来一个数据申请一个数据空间
    2. 采用手拉手的方式,让每个数据空间多出一块地址存放下一个数据空间的地址,即可以通过一个数据的数据空间可以找到与该数据直接相邻的数据空间(数据空间即结点)
    3. 可以充分的利用计算机的存储空间
    
  • Configured nodes: the data linking area Area +

  • Singly linked list

  • One-way circular list

  • Doubly linked list


4. singly linked list

Access can only turn back from the table head position

  • The first node: the first node

  • End nodes: the last node, the link region to null

  • Way linked list of common operations

    operating meaning
    def init(self,node=None) Initialization single list, the head pointer is provided (the first node) of a point to point solution
    def is_empty(self) Determine the list is empty all
    def length(self) The resulting list length (number of nodes linked list)
    def traval(self) To traverse the entire list
    def add(self,item) The first interpolation method to add elements to the list
    def append(self,item) Tail interpolation area to add data to the list item node
    def insert(self,pos,item) To the specified position in the list of nodes insert the data item in the area
    def remove(self,item) Data node data area is equal to delete the list item node
    def search(self,item) Find the list item data area is the junction point of
  • Comparison of the time complexity (the order item list table)

    operating Singly linked list Order table
    Finding Elements O (n) O (1)
    Insert elements O (n) O (n)
    Modify elements O (n) O (1)
    Removing elements O (n) O (n)
    #注:单项链表与顺序表在存储元素时,主要区别如下
    1. 单向链表能够从更加充分的利用计算机的存储空间(单向链表时离散存储,顺序表是顺序存储)
    
    2. 单向链表存储与顺序表存储相同数量的元素时,单向链表耗费的内存空间更大(单向链表的每个结点除了需要开辟数据的存储空间,还开辟了存储下一个结点地址的存储空间,因而耗费存储空间更大)
    
    3. 插入元素与删除元素时虽然者二者耗费的是时间复杂度相同,但本质意义不同:
      单向链表的时间消耗主要耗费在结点的查询中
      顺序表的时间消耗主要耗费在数据的移动中
    

5. singly linked list Listing

#定义一个头结点
class Node(object):
    def __init__(self,elem):
        self.elem = elem
        #初始状态next指向None
        self.next = None

#定义单链表
#目标,需要把结点串联起来
#围绕增删改查的操作时针对链表的对象的方法
#因此对象方法此处定义的均为对象方法
class SingLinkList(object):

    def __init__(self,node=None):
        #这里定义的头结点相当于头指针指向第一个结点
        self.__head = node

    def is_empty(self):
        #判断链表是都为空
        return self.__head == None

    def length(self):
        """链表长度"""
        #cur游标遍历结点,与头指针一样指向头结点
        cur = self.__head
        #记录结点数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def traval(self):
        """遍历整个链表"""
        cur = self.__head
        while cur != None:
            print(cur.elem,end=' ')
            cur = cur.next
    #头插法
    def add(self,item):
        """在头部添加元素(头插法)"""
        node = Node(item)
        node.next = self.__head
        self.__head = node

    #尾插法
    def append(self,item):
        """在链表尾部添加(尾插法)"""
        #先将传入的数据构造成结点
        node  = Node(item)
        if self.is_empty():
            #如果为空,则直接将node作为头结点加入
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self,pos,item):
        """在指定位置添加元素
        :param index 从0开始
        """
        #构建pre指针,也指向头结点
        if pos < 0:
            self.add(item)
        elif pos > linkList.length()-1:
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count < (pos-1):
                count+=1
                pre = pre.next
            #循环推出后,pre指向pos-1的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node

    def remove(self,item):
        """删除结点"""
        cur = self.__head
        pre = None
        while cur != None:
            if cur.elem == item:
                #先判断此结点是否为头结点
                if cur == self.__head:
                    self.__head = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    def search(self,item):
        """查找结点是否存在"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return  False

6. doubly linked list

Can be accessed from front to back, can also be accessed from the back

  • Doubly linked list of common operations

    Referring way linked list, substantially similar, only need to modify part of the method, which is not described in detail here

  • List modification as part of the method

    operating meaning
    def add(self,item) Doubly linked list head interpolation
    def append(self,item) Doubly linked list tail interpolation
    def insert(self,pos,item) Insert elements
    def remove(self,item) Removing elements
    #注:
    1. 双向链表的实现与单项链基本相似,仅在单向链表的每个结点前加入了一个前驱游标(指针prev)
    2. 实现方法中仅修改了四个关于元素添加和删除的方法,其余均与单向链表一致,详情见下面的代码清单
    3. 方便代码重用性,减少代码量,可继承实现单向链表的类(此问题不在赘述,这里重点讨论数据结构如何实现)

Listing 7. doubly linked list

#双向链表的结点重新定义,增加了前驱游标(指针)
class Node(object):
    """双向链表的结点"""
    def __init__(self,item):
        self.elem = item
        self.next = None
        self.prev = None


class DoubleLinkList(object):
    """双链表"""
    def __init__(self,node=None):
        #这里定义的头节点相当于头指针指向第一个节点
        self.__head = node

    #头插法
    def add(self,item):
        """在头部添加元素(头插法)"""
        node = Node(item)
        node.next = self.__head
        self.__head.prev = node
        self.__head = node
        #也可以一下方法,方法不唯一
        # node.next.prev = node

    #尾插法
    def append(self,item):
        """在链表尾部添加(尾插法)"""
        #先将传入的数据构造成节点
        node  = Node(item)
        if self.is_empty():
            #如果为空,则直接将node作为头节点加入
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node
            node.prev = cur

    def insert(self,pos,item):
        """在指定位置添加元素
        :param index 从0开始
        """
        #构建pre指针,也指向头节点
        if pos < 0:
            self.add(item)
        elif pos > self.length()-1:
            self.append(item)
        else:
            cur = self.__head
            count = 0
            while count < (pos-1):
                count+=1
                cur = cur.next
            #循环推出后,pre指向pos-1的位置
            node = Node(item)
            node.next = cur
            node.prev = cur.prev
            node.prev.next = node
            cur.prev = node

    def remove(self,item):
        """删除节点"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                #先判断此节点是否为头节点
                if cur == self.__head:
                    self.__head = cur.next
                    if cur.next:
                        #判断链表是否只有一个结点
                        cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next:
                        cur.next.prev = cur.prev
                break
            else:
                cur = cur.next

8. The one-way circular list

Also be improved on the basis of the check list, the only difference is that the one-way linked list of the next node is not the end point None, but points to the first node

  • Consider the idea: a one-way circular list, for example, first consider the general situation

    After considering the special circumstances such as the header node, the node table, the table is empty are a special case, only one node in the table and the like, in consideration fully, then the code implemented, the more complete structure is achieved

  • Unidirectional operation circular list

    operating meaning
    def init(self,node=None) Initialization single list, the head pointer is provided (the first node) of a point to point solution
    def is_empty(self) Determine the list is empty all
    def length(self) The resulting list length (number of nodes linked list)
    def traval(self) To traverse the entire list
    def add(self,item) The first interpolation method to add elements to the list
    def append(self,item) Tail interpolation area to add data to the list item node
    def insert(self,pos,item) To the specified position in the list of nodes insert the data item in the area
    def remove(self,item) Data node data area is equal to delete the list item node
    def search(self,item) Find the list item data area is the junction point of

    And similar to the basic one-way linked list, and is not too much to say, only need to consider a variety of special circumstances on the basis of the individual on the list, see the following code listing (tested, no problem, test code is omitted here, readers are free test)


9. The one-way circular list Listing

#节点实现
class Node(object):
    def __init__(self,elem):
        self.elem = elem
        #初始状态next指向None
        self.next = None

#定义单向循环链表
class SingleCycleLinkList(object):
    """单向循环链表"""
    def __init__(self,node=None):
        #这里定义的头节点相当于头指针指向第一个节点
        self.__head = node
        if node:
            node.next = node

    def is_empty(self):
        #判断链表是都为空
        return self.__head == None

    def length(self):
        """链表长度"""
        if self.is_empty():
            return  0
        #cur游标遍历节点,与头指针一样指向头节点
        cur = self.__head
        #记录节点数量
        count = 1
        while cur.next != self.__head:
            count += 1
            cur = cur.next
        return count

    def traval(self):
        """遍历整个链表"""
        if self.is_empty():
            return
        cur = self.__head
        while cur.next!= self.__head:
            print(cur.elem,end=' ')
            cur = cur.next
        #退出循环,cur指向尾结点,但是尾节点的元素未打印
        print(cur.elem)

    #头插法
    def add(self,item):
        """在头部添加元素(头插法)"""
        node = Node(item)
        if self.is_empty():
            self.__head = node
            node.next = node
        else:
            # node.next = self.__head
            cur = self.__head
            #退出循环之后cur指向的就是尾结点
            while cur.next != self.__head :
                cur = cur.next
            node.next = self.__head
            cur.next = node
            self.__head = node

    #尾插法
    def append(self,item):
        """在链表尾部添加(尾插法)"""
        #先将传入的数据构造成节点
        node  = Node(item)
        if self.is_empty():
            #如果为空,则直接将node作为头节点加入
            self.__head = node
            node.next = node
        else:
            cur = self.__head
            while cur.next != self.__head:
                cur = cur.next
            cur.next= node
            node.next = self.__head

    def insert(self,pos,item):
        """在指定位置添加元素
        :param index 从0开始
        """
        #构建pre指针,也指向头节点
        if pos < 0:
            self.add(item)
        elif pos > linkList.length()-1:
            self.append(item)
        else:
            pre = self.__head
            count = 0
            while count < (pos-1):
                count+=1
                pre = pre.next
            #循环推出后,pre指向pos-1的位置
            node = Node(item)
            node.next = pre.next
            pre.next = node

#这个方法改写代码较多,请着重查看
    def remove(self,item):
        """删除节点"""
        if self.__head == None:
            return
        cur = self.__head
        #判断该链表是否只有一个结点
        #若只有一个结点
        if cur.next == self.__head:
            #若该结点元素等于item,则删除该节结点
            if cur.elem == item:
                self.__head = None
                return
            #否则该链表没有与此元素相等的结点,直接返回
            return
        pre = None
        while cur.next != self.__head:
            if cur.elem == item:
                #先判断此节点是否为头节点
                if cur == self.__head:
                    #头节点情况
                    #寻找尾结点
                    rear = self.__head
                    while rear.next != self.__head:
                        rear = rear.next
                    self.__head = cur.next
                    rear.next = self.__head
                else:
                    #中间结点删除
                    pre.next = cur.next
                return
            else:
                pre = cur
                cur = cur.next
        #尾部节点
        if cur.elem == item:
             pre.next = cur.next

    def search(self,item):
        """查找节点是否存在"""
        if self.is_empty():
            return False
        cur = self.__head
        while cur.next != self.__head:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        if cur.elem ==item:
            return True
        return  False

10. Other extensions

Doubly linked list can be expanded two-way circular linked list, where the lack of time, to be completed on the future

Guess you like

Origin www.cnblogs.com/Lsg111/p/11489098.html
Recommended