Python数据结构7:无序表,链表对象增删查,链表结点,代码实现

1. 无序表列表:

1.1 定义:

列表是一种数据项按照相对位置存放的数据集。

无序表unordered list是指数据项之间没有顺序的列表。
如一个考试分数的集合“54, 26, 93, 17, 77和31”。
用无序表来表示,就是[54, 26, 93,17, 77, 31]。

2. Python中的无序表List

2.1 定义

List由如下操作定义,为了简单起见,假设表中不存在重复数据项:

  • List():创建一个空列表
  • add(item):添加一个数据项到列表中,假设item原先不存在于列表中
  • remove(item):从列表中移除item,列表被修改,item原先应存在于表中
  • search(item):在列表中查找item,返回布尔类型值
  • isEmpty():返回列表是否为空
  • size():返回列表包含了多少数据项
  • append(item):添加一个数据项到表末尾,假设item原先不存在于列表中
  • index(item):返回数据项在表中的位置
  • insert(pos, item):将数据项插入到位置pos,假设item原先不存在与列表中,同时原列表具有足够多个数据项,能让item占据位置pos
  • pop():从列表末尾移除数据项,假设原列表至少有1个数据项
  • pop(pos):移除位置为pos的数据项,假设原列表存在位置pos

3. 链表

3.1 定义和性质

链表可以实现一个无序表数据格式。

虽然列表数据结构要求保持数据项的前后相对位置,但这种前后位置的保持,并要求数据项依次存放在连续的存储空间

如下图,数据项存放位置并没有规则,但如果在数据项之间建立链接指向,就可以保持其前后相对位置

  • 第一个和最后一个数据项需要显式标记出来,一个是队首,一个是队尾,后面再无数据了。

3.2 节点Node

链表由节点Node组成

每个节点Node包含两部分:

  • 数据项本身: data
  • 指向下一个节点的引用信息: next。
    注意next为None的意思是没有下一个节点了,这个很重要

3.3 Python实现链表的节点Node

class Node:
    def __init__(self, init_data):
        self.data = init_data
        self.next = None

    def get_data(self):
        return self.data

    def get_next(self):
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def set_next(self, new_next):
        self.next = new_next


node1 = Node(54)
print(node1.get_data())  # 54 

node2 = Node(26)
node1.set_next(node2)
print(node2.get_data())  # 26
print(node1.get_next().get_data())  # 26

node3 = Node(93)
node2.set_next(node3)
print(node3.get_data())  # 93
print(node2.get_next().get_data())  # 93

3.4 用链表节点Node实现无序表

链表的第一个和最后一个节点最重要

如果想访问到链表中的所有节点,就必须从第一个节点开始沿着链接遍历下去,就是说从头节点开始,第一个next开始遍历无序表(即头节点的next的节点的数据被访问),直到next是None的时候遍历停止。

  • 所以无序表必须要有对第一个节点的引用信息

3.4.1 头节点head

头节点就是用来保存列表中第一个数据的引用信息的,空表也有head,空表的head是None。意思是self.head就相当于self.head.next(),由于self.head.data()是不存在的,所以这部分就直接省略了。换句话说self.head()就表示了第一个存储数据的节点就等同于self.head.next()。

class UnorderList:
	def __init__(self):
		self.head = None
mylist = UnorderList()
print mylist.head # 结果为None

随着数据项的加入,无序表的head始终指向链条中的第一个节点

  • 注意无序表mylist对象本身并head不包含数据项(数据项在节点中)
  • head只是对首个节点Node的引用
  • 判断空表的isEmpty()很容易实现
return self.head == None

3.4.2 add方法

add方法:向无序表中添加数据项

无序表并没有限定数据项之间的顺序,新数据项可以加入到原表的任何位置

按照实现的性能考虑,应添加到最容易加入的位置上。

要访问到整条链上的所有数据项,必须从表头head开始沿着next链接逐个向后查找,所以添加新数据项最快捷的位置是表头,整个链表的首位置。

def add(self, item):
	temp = Node(item)
	temp.setNext(self.head)
	self.head = temp

3.4.3 size方法

size:从链条头head开始遍历到表尾同时用变量累加经过的节点个数

def size(self):
	current = self.head
	count = 0
	while current != None:
		count = count + 1
		current = current.getNext()
	return count 

3.4.4 search方法

从链表头head开始遍历到表尾,同时判断当前节点的数据项是否为目标

def search(self, item)
	current = self.head
	found = False
	while current != None and not found:
		if current.getData() == item:
			found = True
		else:
			current = current.getNext()
	return found	

3.4.5 remove方法

首先要找到item,这个过程跟search一样,但在删除节点时,需要特别的技巧

  • current指向的是当前匹配数据项的节点
  • 而删除需要把前一个节点的next指向current的下一个节点
  • 所以我们在search current的同时,还要维护前一个(previous)节点的引用

找到item之后,current指向item节点,previous指向前一个节点,开始执行删,需要区分两种情况:

  • current是首个节点
  • current是位于链条中间的节点
def remove(item):
	current = self.head
	previous = None
	found = False
	while not found:
		if current.getData() == item:
			found = True
		else:
			previous = current
			current = current.getNext()
		if previous == None:
			self.head = current.getNext()
		else:
			previous.setNext(current.getNext())

整个链表的对象和操作和节点定义如下:

class Node:
    def __init__(self, init_data):
        self.data = init_data
        self.next = None

    def get_data(self):
        return self.data

    def get_next(self):
        return self.next

    def set_data(self, new_data):
        self.data = new_data

    def set_next(self, new_next):
        self.next = new_next


class UnorderList:
    def __init__(self):
        self.head = None

    def add(self, item):
        temp = Node(item)
        temp.set_next(self.head)
        self.head = temp

    def size(self):
        count = 0
        current = self.head
        while current.next is not None:
            count = count + 1
            current = current.next
        return count

    def search(self, item):
        current = self.head
        found = False
        while current.next is not None:
            current = current.next
            if current.data == item:
                return current.data
        return found

    def remove(self, item):
        current = self.head
        if current.data == item:
            self.head = current.next
        else:
            previous = current
            current = current.next
            while current.next is not None:
                previous = previous.next
                current = current.next
                if current.data == item:
                    previous.next = current.next


my_list = UnorderList()
print(my_list.head)
my_list.add(31)
my_list.add(77)
my_list.add(17)
my_list.add(93)
my_list.add(26)
my_list.add(54)
print(my_list.head.get_data())
print(my_list.size())
print(my_list.search(31))
my_list.remove(31)
print(my_list.size())
print(my_list.search(31))
print(my_list.remove(93))
print(my_list.size())
print(my_list.search(93))

参考文献

本文的知识来源于B站视频 【慕课+课堂实录】数据结构与算法Python版-北京大学-陈斌-字幕校对-【完结!】,是对陈斌老师课程的复习
总结

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值