Linear table
线性表可以看作是一种线性结构(可以分为顺序线性结构,离散线性结构)
Table 1. Linear Type:
Order table
元素存储在一大块连续存储的地址中,首元素存入存储区的起始位置,其余元素顺序存放。 (元素之间的逻辑关系与物理地址上相邻的关系相同)
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
- Built-elements:
Shall ensure that each memory cell of the same size, i.e., of the same type
- 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