A.数据结构(线性表)
A.顺序存储
1.求两个线性表的并集
list1 = ['a', 's', 'd'] list2 = ['a', 's', 'f'] for i in list1: if i not in list2: list2.extend(i) print(list2)
2.查找第i个位置元素的值
def fetch(lis, i): if len(lis) == 0 or i < 1 or i >len(lis) : return 0 else: return lis[i-1] a = ['a', 'x', 'd'] print(fetch(a, 2))
3.在第i个位置插入新的元素,线性表长度加1
def addd(lis, i, new_data): if (i < 1) or (i > len(lis) + 1): # len(lis)+1 是因为要考虑到在列表末尾添加元素 return 0 elif i == len(lis)+1: lis.extend(new_data) return lis else: if i <= len(lis): k = len(lis)-1 lis.extend('1') while k >= i-1: lis[k+1] = lis[k] k = k-1 lis[i-1] = new_data return lis a = ['a', 'x', 'd'] print(addd(a, 4, 'f'))
4.删除第i个位置上的元素
def delete(lis, i): if (len(lis) == 0) or (i < 1) or (i > len(lis) + 1): return 0 elif i < len(lis): # 删除的不是最后一个位置 k = i while k < len(lis): lis[k-1] = lis[k] k = k+1 lis.pop() return lis else: lis.pop() return lis a = ['a', 'x', 'd'] print(delete(a, 1))
B.链表
一·、单链表
class Node(object): # 定义一个节点的类 def __init__(self, elem): self.elem = elem self.next = None # 初始设置下一节点为空 class SingleLinkList(object): def __init__(self, node=None): # 使用一个默认参数,传入第一个结点时接收,没有传入时,默认是空链表 self.__head = node def is_empty(self): # 判断链表是否为空 空返回Ture return self.__head == None def length(self): '''链表长度''' # cur为游标,用来遍历节点,是移动的 cur = self.__head # count记录节点数量 count = 0 while cur != None: count += 1 cur = cur.next return count def travel(self): '''遍历整个列表''' cur = self.__head while cur != None: print(cur.elem,end = ' ') # ''中必须有空格。'空格',这样两个元素打印出来中间不会连着 cur = cur.next print("\n") # 打印完整个链表以后换行 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(): # 特殊情况,链表为空 self.__head = node else: cur = self.__head while cur.next != None: # 游标最后是在最后一个节点 cur = cur.next cur.next = node def insert(self,pos,item): '''指定位置添加元素''' if pos <= 0: # 想要插入节点的位置小于等于0,都当做在链表头部添加节点 self.add(item) elif pos > self.length(): self.append(item) else: per = self.__head count = 1 while count < pos-1: count += 1 per = per.next # 循环退出时,per这个游标在pos-1位置,指定位置的前面一个节点 node = Node(item) node.next = per.next # 顺序不能变,先加入原链表,再破坏原链表 per.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 else: # 要删除的节点不是第一个节点 pre.next = 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 if __name__ == "__main__": l1 = SingleLinkList() print(l1.is_empty()) # true l1是一个空链表 l1.append(3) l1.add(999) l1.insert(2,2) l1.travel() # 999 2 3 print(l1.length()) print(l1.is_empty()) l1.remove(999) l1.travel() # 2 3
print(l1.search(999)) # False
二、双向链表
class Node(object): # 定义一个节点的类 def __init__(self, item): self.elem = item self.prev = None #指向前驱结点 self.next = None #指向后继结点 class LinkedListTwoway(object): def __init__(self, node=None): # 使用一个默认参数,传入第一个结点时接收,没有传入时,默认是空链表 self.__head = node def is_empty(self): '''判断链表是否为空 空返回Ture''' return self.__head == None def length(self): '''链表长度''' # cur为游标,用来遍历节点,是移动的 cur = self.__head # count记录节点数量 count = 0 while cur != None: count += 1 cur = cur.next return count def travel(self): '''遍历整个列表''' cur = self.__head while cur != None: print(cur.elem,end = ' ') # ''中必须有空格。'空格',这样两个元素打印出来中间不会连着 cur = cur.next print("\n") # 打印完整个链表以后换行 def add(self,item): '''链表头部添加元素''' node = Node(item) if self.is_empty(): # 特殊情况,链表为空 self.__head = node else: node.next = self.__head node.next.prev = node # self.__head.prev = node self.__head = node def append(self,item): '''链表尾部添加元素''' node = Node(item) if self.is_empty(): # 特殊情况,链表为空 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): '''指定位置添加元素''' if pos <= 0: # 想要插入节点的位置小于等于0,都当做在链表头部添加节点 self.add(item) elif pos > self.length(): self.append(item) else: count = 1 # 符合用户习惯,从1开始计数 cur = self.__head while count < pos-1: count += 1 cur = cur.next # 循环退出时,per这个游标在pos-1位置,指定位置的前面一个节点 node = Node(item) node.next = cur.next # 顺序不能变,先加入原链表,再破坏原链表 cur.next.prev = node node.prev = cur cur.next = node def remove(self,item): '''删除节点''' if self.is_empty(): return 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 != None: #特殊情况:如果删除最后一个节点,则不能进入执行这一句 cur.next.prev = cur.prev break # 删除完退出循环 else: # 没要找到要删除的节点,两个游标继续往后 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 if __name__ == "__main__": l1 = LinkedListTwoway() print(l1.is_empty()) # true l1是一个空链表 l1.append(3) l1.add(999) l1.insert(2,2) l1.travel() # 999 2 3 print(l1.length()) # 3 print(l1.is_empty()) # False l1.remove(999) l1.travel() # 2 3 print(l1.search(999)) # False
三、单向循环链表
class Node(object): # 定义一个节点的类 def __init__(self, elem): self.elem = elem self.next = None # 初始设置下一节点为空 class CircularLinkedList(object): def __init__(self, node=None): # 只是一个空链表也可以哈 if node: # 构造非空链表,初始链表默认只有一个节点,其地址域指向自己 node.next = node self.__head = node def is_empty(self): # 判断链表是否为空 空返回Ture return self.__head == None def length(self): # 链表长度 cur = self.__head count = 1 # count记录节点数量 # 需要从1开始计数,因为游标走到最后一个节点时不再进入循环体 # 前面单向链表和双向链表的游标走到最后一步还会进入循环体 if self.is_empty(): return 0 while cur.next != self.__head: count += 1 cur = cur.next return count def travel(self): '''遍历整个列表''' if self.is_empty(): return 0 cur = self.__head while cur.next != self.__head: print(cur.elem, end=' ') # ''中必须有空格。'空格',这样两个元素打印出来中间不会连着 cur = cur.next print(cur.elem) print("\n") # 打印完整个链表以后换行 def add(self,item): '''链表头部添加元素''' node = Node(item) if self.is_empty(): # 特殊情况:空链表 self.__head = node node.next = node else: cur = self.__head while cur.next != self.__head: cur = cur.next # 退出循环后,cur指向最后一个节点,找到了尾结点 node.next = self.__head # 新节点指向原来的第一个节点 self.__head = node # 头结点指向新的第一个节点 cur.next = node # 尾结点还要指向第一个结点 def append(self,item): '''链表尾部添加元素''' node = Node(item) if self.is_empty(): # 特殊情况,链表为空 self.__head = node self.__head.next = self.__head else: cur = self.__head while cur.next != self.__head: # 游标最后是在最后一个节点 cur = cur.next node.next = cur.next # 新节点指向 最后一个游标指向的东西(第一个节点) cur.next = node # 原最后一个节点指向新的最后一个节点 def insert(self,pos,item): '''指定位置添加元素''' if pos <= 0: # 想要插入节点的位置小于等于0,都当做在链表头部添加节点 self.add(item) elif pos > self.length(): self.append(item) else: cur = self.__head count = 1 while count < pos-1: count += 1 per = cur.next # 循环退出时,per这个游标在pos-1位置,指定位置的前面一个节点 node = Node(item) node.next = cur.next # 顺序不能变,先加入原链表,再破坏原链表 cur.next = node def remove(self,item): '''删除节点''' cur = self.__head pre = None if self.is_empty(): return 0 while cur.next != self.__head: if self.is_empty(): return 0 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 # 退出循环时,cur指向的结点并没有进行操作,也就是没有执行循环体 if cur.item == item: # 要删除的节点是最后一个节点 if cur == self.__head: # 特殊情况:链表只有一个节点 self.__head = None return pre.next = cur.next # pre.next = self.__head 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 if __name__ == "__main__": l1 = CircularLinkedList() print(l1.is_empty()) # true l1是一个空链表 l1.append(3) l1.add(999) l1.insert(2,2) l1.travel() # 999 2 3 print(l1.length()) print(l1.is_empty()) l1.remove(999) l1.travel() # 2 3 print(l1.search(999)) # False