Python数据结构练习之每日快递

以下题目摘自人民邮电出版社《数据结构——Python语言描述》82页:

综合实验3 每日快递
实验目的:深入理解循环单链表的存储结构,熟练掌握循环单链表的基本操作。
实验背景:瑶湖快递的快递员张小明每日负责 N 市高新技术开发区中 10 个居民小区的快递派送任务,张小明会在每天上午 9 点和下午 2 点分别进行两次派送,图 2-38 所示(笔者注:图找不到,就不贴了)为张小明每日的派送路线。快递公司规定,在派送过程中,快递员还应该接收小区内已预定寄出的快递,若某小区需要派送的快递个数和接收的快递个数均为零,快递员则不需要前往该小区,而是直接前往下一小区进行派送。每日派送结束后,公司对每位快递员去过的小区数目及收寄快递的数量进行清点。假设表 2-19 所示为张小明今日的工作记录,请借助于循环单链表来实现公司对张小明当日派送任务的清点。
表 2-19 张小明今日工作记录
在这里插入图片描述
实验内容:创建文件 ex030502_03.py,并在其中编写快递派送清算程序,具体如下。
(1)创建循环单链表 A ,并将小区编号作为参数创建相应结点,并依次链入循环单链表 A 中。
(2)通过扫描 A ,记录下快递员走过的小区个数,并将派送快递的总个数、接收快递的总个数存入当前结点的数据域中。
(3)输出快递员走过的小区个数、派送快递的总个数。
实验提示:
(1)每个结点应有两个数据域,分别用于存放收件数和派件数。
(2)可借助数组或手动输入来更新每个小区派送和接收快递的个数。
(3)可借助数组或列表来完成计数操作。

看完题目,笔者就觉得这题出得不太好,因为这样的题目犯不上使用循环单链表。再细读一遍实验提示之后,觉得这条题目确实是存在令人费解的地方的。特别是这句:

可借助数组或列表来完成计数操作

这句完全是不需要做的,直接使用三个变量即可。

还有,题目说

将小区编号作为参数创建相应结点

但其实我们可以在创建的同时存值进去,不用这么麻烦。

因此,笔者打算先贴一份不完全按照题目要求的代码:

class Node:
    def __init__(self,send=None,receive=None,next=None):
        self.send=send
        self.receive=receive
        self.next=next
class CircularSingleLinkedList:
    def __init__(self):
        self.head=Node()
        self.head.next=self.head
    def creat(self,lst):
        cur=self.head
        for i in lst:
            cur.next=Node(i[0],i[1],self.head)
            cur=cur.next
    def update(self,lst):
        cur=self.head.next
        for i in lst:
            cur.send,cur.receive=i[0],i[1]
            cur=cur.next
    def count(self):
        cur=self.head.next
        cnt,sumsend,sumreceive=0,0,0
        while cur!=self.head:
            if cur.send!=0 or cur.receive!=0:
                cnt+=1
                sumsend+=cur.send
                sumreceive+=cur.receive
            cur=cur.next
        return [cnt,sumsend,sumreceive]

if __name__ == '__main__':
    a=CircularSingleLinkedList()
    lst1=[[8,0],[5,2],[6,4],[0,0],[8,0],[0,0],[2,1],[2,0],[1,1],[3,1]]
    lst2=[[2,1],[1,3],[2,5],[4,0],[7,0],[9,0],[1,0],[1,2],[1,1],[0,0]]
    a.creat(lst1)
    print(a.count())
    a.update(lst2)
    print(a.count())

##输出:
##[8, 35, 9]
##[9, 28, 12]

可以看到,这里的代码没有用到循环单链表的特性,只不过把它当单链表使用了。然后,像上面所讲的,代码是使用三个变量来统计数据的,没有用到数组,也没有先建好再存值。

但是,这毕竟是在做题目,因此笔者不得不贴出这一份尽量符合题目要求的代码:

class Node:
    def __init__(self,send=None,receive=None,next=None):
        self.send=send
        self.receive=receive
        self.next=next
class CircularSingleLinkedList:
    def __init__(self):
        self.head=Node()
        self.head.next=self.head
    def creat(self,n):
        cur=self.head
        for i in range(n):
            cur.next=Node(None,None,self.head)
            cur=cur.next
    def update(self,lst):
        cur=self.head.next
        for i in lst:
            cur.send,cur.receive=i[0],i[1]
            cur=cur.next
    def count(self):
        cur=self.head.next
        cnt=0
        cntlst=[]
        while cur!=self.head:
            if cur.send!=0 or cur.receive!=0:
                cnt+=1
                cntlst.append([cur.send,cur.receive])
            cur=cur.next
        return [cnt,sum(i[0] for i in cntlst),sum(i[1] for i in cntlst)]

if __name__ == '__main__':
    a=CircularSingleLinkedList()
    n=10
    lst1=[[8,0],[5,2],[6,4],[0,0],[8,0],[0,0],[2,1],[2,0],[1,1],[3,1]]
    lst2=[[2,1],[1,3],[2,5],[4,0],[7,0],[9,0],[1,0],[1,2],[1,1],[0,0]]
    a.creat(n)
    a.update(lst1)
    print(a.count())
    a.update(lst2)
    print(a.count())

##输出:
##[8, 35, 9]
##[9, 28, 12]

这份代码修改了creat方法和count方法,主程序中也做了相应改变。可以看到,如果完全遵照题目的意思来的话,代码是很不优美的,而且循环的性质依然没有用上。

其实,为了使用到循环的特性,我们可以写一份更丑的代码,即,使用三遍循环,第一遍建立链表,同时存上午的值;第二遍遍历链表,记录上午数据,并更新结点为下午的数据;第三遍再遍历一次链表,记录下午数据。由于这么写代码实在太过冗长,且耦合度极高,这里就不贴出了。

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值