数据结构与算法——6. 抽象数据类型:无序表与有序表及其链表实现

一、无序表(unordered list)抽象数据类型

1. 无序表的定义

列表是一种数据项按照相对位置存放的数据集,有时也称为“无序表unordered list”,其中数据项只按照存放位置来索引,如第1个、第2个……、最后一个等。

如一个考试分数的集合“54, 26, 93, 17, 77和31”,如果用无序表来表示,就是[54, 26, 93, 17, 77, 31]。

2. 采用链表实现无序表

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

因此,我们可以采用链表的结构来实现无序表。

(1)链表

如下图,链表中的数据项存放位置并没有规则,通过在数据项之间建立链接指向,来保持其前后相对位置

在这里插入图片描述

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

(2)链表节点

链表实现的最基本元素是节点Node,上图中的head、54、93、end等,就是链表的一个个节点。

每个节点至少要包含2个信息:数据项本身(data),以及指向下一个节点的引用信息(next)

在这里插入图片描述

注意:next为None时,表示没有下一个节点了!

(3)python实现链表节点

class Node:
    def __init__(self):
        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

(4)python实现链表

先来分析一下步骤:

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

    如果想访问到链表中的所有节点,就必须从第一个节点开始沿着链接遍历下去。所以无序表必须要有对第一个节点的引用信息。

  • 添加数据项:

    由于无序表并没有限定数据项之间的顺序,出于对性能的考虑,应添加到表头head节点上。
    在这里插入图片描述

​ 注意:两步的顺序不要搞反!否则会丢失head对节点93的引用。

  • 统计数据项的数量:

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

  • 搜索数据项是否在链表中:

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

  • 移除数据项:

    首先要找到item,这个过程跟上面的的搜索方法一样,但在删除节点时,需要特别的技巧。

    在这里插入图片描述

    需要把前一个节点的next指向current的下一个节点

完整的代码如下:

class UnorderedList:

    def __init__(self):
        self.head = None

    def is_empty(self):
        """判断链表是否为空"""
        return self.head == None

    def add(self,item):
        """添加数据项"""
        temp = Node(item)
        # 步骤顺序千万不要搞错
        temp.set_next(self.head)
        self.head = temp

    def size(self):
        """返回链表大小"""
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.get_next()

        return count

    def search(self,item):
        """查询链表是否包含指定数据项"""
        current = self.head
        found = False
        while current != None and not found:
            if current.get_data() == item:
                found = True
            else:
                current = current.get_next()

        return found

    def remove(self,item):
        """移除指定元素"""
        current = self.head
        previous = None
        found = False
        while not found:
            if current.get_data() == item:
                found = True
            else:
                previous = current
                current = current.get_next()

        if previous == None:
            self.head = current.get_next()
        else:
            previous.set_next(current.get_next())

二、有序表(Ordered List)抽象数据类型

1. 有序表的定义

有序表是一种数据项依照其某可比性质(如整数大小、字母表先后)来决定在列表中的位置。

2. 使用python实现有序表

下面对数据项的讨论并不仅适用于整数,可适用于所有定义了__gt__方法(即>操作符)的数据类型。

同样采用链表方法实现有序表,Node定义相同。需要记住的是,数据项的相对位置,取决于它们之间的“大小”比较。

有序表的节点与无序表的一样,并且大部分方法与无序表的方法也一样,只有search方法和add方法有所不同:

search方法:

  • 在无序表的search中,如果需要查找的数据项不存在,则会搜遍整个链表,直到表尾;

  • 对于有序表来说,可以利用链表节点有序排列的特性,来为search节省不存在数据项的查找时间。

    一旦当前节点的数据项大于(或小于)所要查找的数据项,则说明链表后面已经不可能再有要查找的数据项,可以直接返回False。

    def search(self,item):
            current = self.head
            found = False
            stop = False
            while current != None and not found and not stop:
                if current.get_data() == item:
                    found = True
                else:
                    if current.get_data() > item:
                        stop = True
                    else:
                        current = current.get_next()
    
    

add方法:

  • 相比无序表,有序表添加数据项时,必须保证加入的数据项添加在合适的位置,以维护整个链表的有序性。

  • 以从小到大的顺序为例:需要先找到恰好大于新数据项的数据项,然后将新数据项插入该数据项的前面。

    在这里插入图片描述

    def add(self,item):
        current = self.head
        previous = None
        stop = False
        while current != None and not stop:
            if current.get_data() > item:
                stop = True
            else:
                previous = current
                current = current.get_next()
    
        temp = Node(item)
        if previous == None:
            temp.set_next(self.head)
            self.head = temp
        else:
            temp.set_next(current)
            previous.set_next(temp)
    
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花_城

你的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值