数据结构与算法学习笔记 (二) 栈 链表 队列 树 堆 图 并查集 (2)

链表属于常见的一种线性结构,对于插入和移除而言,时间复杂度都为 O(1)
但是对于搜索操作而言,不管从链表的头部还是尾部,都需要遍历 O(n),所以最好复杂度为 O(1),最坏的情况就是从头部遍历到尾部才搜索出对应的元素,所以最坏复杂度为 O(n),平均复杂度为 O(n)。
归纳如下:
* 最好复杂度为 O(1)
* 最坏复杂度为 O(n)
* 平均复杂度为 O(n)
双向链表(Double_linked_list)也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。双链表具体实现代码:

class Node(object): #双向链表节点 def __init__(self, item): self.item = item self.next = None self.prev = None class DLinkList(object): #双向链表 def __init__(self): self._head = None def is_empty(self): #判断链表是否为空 return self._head == None def get_length(self): #返回链表的长度 cur = self._head count = 0 while cur != None: count = count+1 cur = cur.next return count def travel(self): #遍历链表 cur = self._head while cur != None: print(cur.item) cur = cur.next print("") def add(self, item): #头部插入元素 node = Node(item) if self.is_empty(): #如果是空链表 将_head指向node self._head = node else: #将node的next指向_head的头节点 node.next = self._head #将_head的头节点的prev指向node self._head.prev = node #将_head指向node self._head = node def append(self, item): #尾部插入元素 node = Node(item) if self.is_empty(): #如果是空链表将_head指向node self._head = node else: #移动到链表尾部 cur = self._head while cur.next != None: cur = cur.next #将尾节点cur的next指向node cur.next = node #将node的prev指向cur node.prev = cur def search(self, item): #查找元素是否存在 cur = self._head while cur != None: if cur.item == item: return True cur = cur.next return False def insert(self, pos, item): #在指定位置添加节点 if pos <= 0: self.add(item) elif pos > (self.length()-1): self.append(item) else: node = Node(item) cur = self._head count = 0 #移动到指定位置的前一个位置 while count < (pos - 1): count += 1 cur = cur.next #将node的prev指向cur node.prev = cur #将node的next指向cur的下一个节点 node.next = cur.next #将cur的下一个节点的prev指向node cur.next.prev = node #将cur的next指向node cur.next = node def remove(self, item): #删除元素 if self.is_empty(): return else: cur = self._head if cur.item == item: #如果首节点的元素即是要删除的元素 if cur.next == None: #如果链接只有这一个节点 self._head = None else: #将第二个节点的prev设置为None cur.next.prev = None #将_head指向第二个节点 self._head = cur.next return while cur != None: if cur.item == item: #将cur的前一个节点的next指向cur的后一个节点 cur.prev.next = cur.next #将cur的后一个节点的prev指向cur的前一个节点 cur.next.prev = cur.prev break cur = cur.next

举个列子,交换单链表里两个链点

class Node: def __init__(self, data): self.data = data self.next = None class Linkedlist: def __init__(self): self.head = None def print_list(self): print("linked_list:") temp = self.head new_list = [] while temp is not None: new_list.append(temp.data) temp = temp.next print(new_list) def insert(self, new_data): new_node = Node(new_data) new_node.next = self.head self.head = new_node def swapNodes(self, d1, d2): prevD1 = None prevD2 = None if d1 == d2: return else: D1 = self.head while D1 is not None and D1.data != d1: prevD1 = D1 D1 = D1.next D2 = self.head while D2 is not None and D2.data != d2: prevD2 = D2 D2 = D2.next if D1 is None and D2 is not None: return if prevD1 is not None: prevD1.next = D2 else: self.head = D2 if prevD2 is not None: prevD2.next = D1 else: self.head = D1 temp = D1.next D1.next = D2.next D2.next = temp if __name__ == \'__main__\': list = Linkedlist() list.insert(5) list.insert(4) list.insert(3) list.insert(2) list.insert(1) list.print_list() list.swapNodes(1, 4) print("After swampping") list.print_list() #输出 linked_list: [1, 2, 3, 4, 5] After swampping linked_list: [4, 2, 3, 1, 5]

=~休息十分钟 再继续吧~=

队列

队列 (queue) 是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列符合先进先出[FIFO]的原则。因为要排队的第一个项目,最终将是第一个要出列的项目,如在现实生活中的队列,先来的站在队列前面,后来的就只能站在队列后面啦。
队列有两种实现形式,分为两种:数组和链表。

class Node(object): def __init__(self, elem, next = None): self.elem = elem #表示对应的元素值 self.next = next #表示下一个链接的链点 #创建Queue类 以链表形式的队列并初始化对应的内参 class Queue(object): def __init__(self): self.head = None #头部链点为None self.rear = None #尾部链点为None #添加is_empty函数 判断队列是否为空 def is_empty(self): return self.head is None #判断队列是否为空 #添加enqueue(elem)函数 往队列中添加一个elem元素 def enqueue(self, elem): p = Node(elem) #初始化一个新的点 if self.is_empty(): self.head = p #队列头部为新的链点 self.rear = p #队列尾部为新的链点 else: self.rear.next = p #队列尾部的后继是这个新的点 self.rear = p #让队列尾部指针指向这个新的点 #添加dequeue函数 从队列头部删除一个元素 def dequeue(self): if self.is_empty(): print("empty") #队列为空则退出dequeue操作 else: result = self.head.elem #result为队列头部元素 self.head = self.head.next #改变队列头部指针位置 return result #peek() 查看队列头部的元素 def peek(self): if self.is_empty(): print("NOT_FOUND") else: return self.head.elem #打印出队列的所有元素 def print_queue(self): print("queue") temp = self.head myqueue = [] #暂存队列数据 while temp is not None: myqueue.append(temp.elem) temp = temp.next print(myqueue) class Queue(): def __init__(self): self.entries = [] #表示队列内的参数 self.length = 0 #表示队列的长度 self.front = 0 #表示队列头部位置 def enqueue(self, item): self.entries.append(item) #往队列里加元素 self.length = self.length + 1 #队列长度增1 def dequeue(self): self.length = self.length - 1 dequeued = self.entries[self.front] #dequeued是队首元素 self.front -= 1 #队首位置减少1 self.entries = self.entries[self.front:] #队列元素更新为退队之后的队列 return dequeued def peek(self): return self.entries[0] #直接返回队列的队首元素 复杂度分析

队列属于常见的一种线性结构,对于出队和进队而言,时间复杂度都为 O(1)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwzxf.html