• 数据结构与算法学习(一):线性表


    一.什么是线性表

    线性表是最基本、最简单、也是最常用的一种数据结构,它的定义是:由零个或多个数据元素组成的有限序列,线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。

    线性表的两种物理结构:顺序存储结构和链式存储结构

    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))
    

      

  • 相关阅读:
    软件项目技术点(7)——在canvas上绘制自定义图形
    软件项目技术点(4)——实现点击选中画布上元素
    软件项目技术点(5)——在canvas上绘制动态网格线
    软件项目技术点(3)——多画布职责分离
    软件项目技术点(1)——游戏主循环机制
    Node.js Express 框架
    nodejs进阶(7)—async异步流程控制
    利用shell脚本快速定位日志
    MySQL数据库查询所有表名
    MySQL数据库中查询表的所有列名
  • 原文地址:https://www.cnblogs.com/wangxiayun/p/8471005.html
Copyright © 2020-2023  润新知