1. 双向链表
单向链表只有一个方向,结点只有一个后继指针next指向后面的结点。而双向链表,顾名思义,它支持两个方向,每个结点不止有一个后继指针next指向后面的结点,还有一个前驱指针last指向前面的结点。
2. 双向链表的实现
'''
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
append(item) 链表尾部添加元素
add(item) 链表头部添加元素
insert(pos, item) 指定位置添加元素
search(item) 查找节点是否存在
remove(item) 删除节点
'''
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
self.last = None
class DoubleLinkList(object):
def __init__(self, node=None):
self.__head = node
def is_empty(self):
'''链表是否为空'''
return self.__head == None
def length(self):
'''链表长度'''
long = 0
cur = self.__head
while cur != None:
long += 1
cur = cur.next
return long
def travel(self):
'''遍历整个链表'''
cur = self.__head
while cur != None:
print(cur.item, end=' ')
cur = cur.next
print()
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.last = cur
def add(self, item):
'''链表头部添加元素'''
node = Node(item)
if self.is_empty():
self.__head = node
else:
node.next = self.__head
self.__head.last = node
self.__head = node
def insert(self, pos, item):
'''指定位置添加元素'''
if pos <= 0:
self.add(item)
elif pos >= self.length():
self.append(item)
else:
node = Node(item)
long = 0
cur = self.__head
while long < pos:
cur = cur.next
long += 1
node.next = cur
node.last = cur.last
cur.last.next = node
cur.last = node
def search(self, item):
'''查找节点是否存在'''
if self.is_empty():
return False
else:
cur = self.__head
while cur != None:
if cur.item ==item:
return True
cur = cur.next
return False
def remove(self, item):
'''删除节点'''
if self.is_empty():
return None
elif self.__head.item == item:
cur = self.__head
if self.length() == 1:
self.__head = None
return None
else:
self.__head = cur.next
else:
cur = self.__head
while cur.next != None:
if cur.item == item:
cur.last.next = cur.next
cur.next.last = cur.last
return None
cur = cur.next
if cur.item == item:
cur.last.next = None
return None
return None
3. 栈
关于“栈”,我有一个非常贴切的例子,就是一摞叠在一起的盘子。我们平时放盘子的时候,都是从下往上一个一个放;取的时候,我们也是从上往下一个一个地依次取,不能从中间任意抽出。后进者先出,先进者后出,这就是典型的“栈”结构。
从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。
为什么还要用这个“操作受限”的“栈”呢?
答:事实上,从功能上来说,链表确实可以替代栈,但你要知道,特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错。当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。
4. 栈的实现
用顺序表的方式实现栈
'''
Stack() 创建一个新的空栈
push(item) 添加一个新的元素item到栈顶
pop() 弹出栈顶元素
peek() 返回栈顶元素
is_empty() 判断栈是否为空
size() 返回栈的元素个数
'''
class Stack(object):
def __init__(self):
self.__items = []
def is_empty(self):
'''is_empty() 判断栈是否为空'''
return self.__items == []
def push(self, item):
'''push(item) 添加一个新的元素item到栈顶'''
self.__items.append(item)
def pop(self):
'''pop() 弹出栈顶元素'''
self.pop()
def peek(self):
'''peek() 返回栈顶元素'''
if self.is_empty():
return None
else:
return self.__items[-1]
def size(self):
'''size() 返回栈的元素个数'''
# i = 0
# for item in self.__items:
# i += 1
# return i
return len(self.__items)
5. 小结
这堂课后,我学会了栈的实现,也对数据结构有了更加深刻的认识了。这节课的笔记写的不是那么的及时,以后还是要得更加努力地学习呀!