一.什么是线性表
线性表是最基本、最简单、也是最常用的一种数据结构,它的定义是:由零个或多个数据元素组成的有限序列,线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
线性表的两种物理结构:顺序存储结构和链式存储结构
1.顺序存储结构
定义:用一段地址连续的存储单元依次存储线性表的数据元素
顺序表的优点与缺点
优点:可以快速的存取访问表中的元素
缺点:插入和删除麻烦,需要移动大量的数据,容易造成存储空间碎片
顺序表的实现
#顺序表的实现
class SeqList(object):
def __init__(self,max=10):
self.max = max
self.num = 0
self.data = [None] * self.max
def isEmpty(self):
return self.num is 0
def isFull(self):
return self.num is self.max
def __getitem__(self,i):
if not isinstance(i,int):
raise TypeError
if 0 <= i < self.num:
return self.data[i]
else:
raise IndexError
def __setitem__(self,key,value):
if not isinstance(key,int):
raise TypeError
if 0 <= key < self.num:
self.data[key] = value
else:
raise IndexError
def getLoc(self,value):
n = 0
for j in range(self.num):
if self.data[j] == value:
return j
if j == self.num:
return -1
def count(self):
return self.num
def append(self,value):
if self.num > self.max:
print('The list is full')
else:
self.data[self.num] = value
self.num += 1
def insert(self,i,value):
if not isinstance(i,int):
raise TypeError
if i < 0 and i > self.num:
raise IndexError
for j in range(self.num,i,-1):
self.data[j] = self.data[j-1]
self.data[i] = value
self.num += 1
def remove(self,i):
if not isinstance(i,int):
raise TypeError
if i < 0 and i >= self.num:
raise IndexError
for j in range(i,self.num):
self.data[j] = self.data[j+1]
self.num -= 1
def printList(self):
for i in range(0,self.num):
print(self.data[i])
def destory(self):
self.__init__()
2.链式存储结构
定义:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域,最后一个节点指针为空(Null)
链表的优点:插入和删除方便,不需要移动大量的数据,使用于插入和删除频繁的操作
链表的缺点:查找十分麻烦,每次查找都需要遍历链表
单链表(动态链表)的实现:
#链表的实现
class ListNode(object):
def __init__(self,data):
self.data = data
self.next = None
def getData(self):
return self.data
def setData(self,newData):
self.data = newData
def getNext(self):
return self.next
def setNext(self,nextNode):
self.next = nextNode
class UnorderedList(object):
def __init__(self):
self.head = None
def getHead(self):
return self.head
def isEmpty(self):
return self.head is None
def add(self,item):
node = ListNode(item)
node.next = self.head
self.head = node
def size(self):
current = self.head
count = 0
while current is not None:
count += 1
current = current.getNext
return count
def search(self,item):
current = self.head
found = False
while current is not None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def append(self,item):
node = ListNode(item)
if self.isEmpty():
self.head = node
else:
current = self.head
while current.getNext() is not None:
current = current.getNext()
current.setNext(node)
def remove(self,item):
current = self.head
privious = None
found = False
while not found:
if current.getData() == item:
found = True
else:
privious = current
current = current.getNext()
if privious is None:
self.head = current.getNext()
else:
privious.setNext(current.getNext())
def getValue(self):
current = self.head
currarr = []
while current != None:
currarr.append(current.getData())
current = current.getNext()
return currarr
静态链表:用数组描述的链表
定义:对于线性链表,也可用一维数组来进行描述。第一个下标和最后一个下标不存放任何数据,第一个游标指向第一个没有数据的下标,最后一个游标指向第一个有数据的下标,最后一个有数据的游标指向0
优点:这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针(游标),故仍具有链式存储结构的主要优点
缺点:表长难以确定,失去了顺序存储结构随机存储的特性
下图为静态链表的插入操作:
循环链表
定义:循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环
循环链表的特点:
1.循环链表中没有NULL指针。涉及遍历操作时,其终止条件就不再是像非循环链表那样判别p或p->next是否为空,而是判别它们是否等于某一指定指针,如头指针或尾指针
2.在单链表中,从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。而在单循环链表中,从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现
循环链表的实现:
class Node(object):
def __init__(self,item):
self.item = item
self.next = None
class CycleSingleLinkList(object):
def __init__(self,node=None):
self.head = node
def isEmpty(self):
return self.head is None
def length(self):
if self.isEmpty():
return 0
current = self.head
count = 1
while current.next != self.head:
count += 1
current = current.next
return count
def travel(self):
if self.isEmpty():
print("")
return
current = self.head
while current.next != self.head:
print(current.item,end="")
current = current.next
print(current.item,end="")
print("")
def add(self,item):
node = Node(item)
if self.isEmpty():
node.next = node
self.head = node
else:
current = self.head
while current.next != self.head:
current = current.next
node.next = self.head
self.head = node
current.next = node
def append(self,item):
node = Node(item)
if self.isEmpty():
self.head = node
node.next = self.head
else:
current = self.head
while current.next != self.head:
current = current.next
current.next = node
node.next = self.head
def insert(self,pos,item):
if pos <= 0:
self.add(item)
elif pos > (self.length() - 1):
self.append(item)
else:
node = Node(item)
current = self.head
count = 0
while count < (pos - 1):
count += 1
current = current.next
node.next = current.next
current.next = node
def remove(self,item):
if self.isEmpty():
return
current = self.head
pre = None
if current.item == item:
if current.next != self.head:
while current.next != self.head:
current = current.next
current.next = self.head.next
self.head = self.head.next
else:
self.head = None
else:
pre = self.head
while current.next != self.head:
if current.item == item:
pre.next = current.next
return
else:
pre = current
current = current.next
if current.item == item:
pre.next = current.next
def search(self,item):
if self.isEmpty():
return False
current = self.head
if current.item == item:
return true
while current.next != self.head:
current = current.next
if current.item == item:
return True
return False
if __name__ == '__main__':
l = CycleSingleLinkList()
l.append(1)
l.append(2)
l.append(3)
l.add(4)
l.insert(2,5)
l.remove(5)
print(l.search(5))
print(l.length())
l.travel()
双向链表
定义:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表
双向链表实现:
#双向循环链表
class Node(object):
def __init__(self,data=None):
self.data = data
self.next = None
self.prev = None
class dblLinkList(object):
def __init__(self):
head = Node()
tail = Node()
self.head = head
self.tail = tail
self.head.next = self.tail
self.tail.pre = self.head
def len(self):
length = 0
node = self.head
while node.next != self.tail:
length += 1
node = node.next
return length
def append(self,data):
node = Node(data)
pre = self.tail.pre
pre.next = node
node.pre = pre
self.tail.pre = node
node.next = self.tail
return node
def get(self,index):
length = self.len()
index = index if index >= 0 else length + index
if index >= length or index < 0:return None
node = self.head.next
while index:
node = node.next
index -= 1
return node.data
def set(self,index,data):
node = self.get(index)
if node:
node.data = data
return node
def insert(self,index,data):
length = self.len()
if abs(index + 1) > length:
return False
index = index if index >= 0 else index + 1 + length
next_node = self.get(index)
if next_node:
node = Node(data)
pre_node = next_node.pre
pre_node.next = node
node.pre = pre_node
node.next = next_node
next_node.pre = node
return node
def delete(self,index):
node = self.get(index)
if node:
node.pre.next = node.next
node.pre.pre = node.pre
return True
return False
def clear(self):
self.head.next = self.tail
self.tail.pre = self.head
if __name__ == '__main__':
l = dblLinkList()
l.append(111)
l.append(222)
l.append(333)
print(l.get(0))
print(l.get(1))
print(l.get(2))