当前位置:   article > 正文

python数据结构与算法之顺序表和单链表的创建以及使用顺序和链式存储的线性表解决约瑟夫(Josephus)问题_python中sqlist(26)

python中sqlist(26)

一、顺序表

1.1 定义与特点

定义:线性表的顺序存储结构是把线性表中的所有元素,按照其逻辑顺序依次存储到计算机内存单元的 从指定存储位置开始的 一块连续存储空间中,称为顺序表。
特点:
1.在线性表中逻辑上相邻的元素在物理存储位置上也有同样的相邻。
2.可按照数据元素的位序号进行随机存取。
3.进行插入、删除操作需要移动大量的数据元素
4.需要进行存储的空间的预先分配,可能会造成空间浪费,单存储的密度较高。

1.2 创建顺序表

1.2.1 代码

class sqlist:
    def __init__(self,maxsize):
        self.curlen = 0
        self.maxsize = maxsize
        self.listitem = [None]*self.maxsize

    def is_empty(self):
        """判断顺序表是否为空"""
        return self.curlen == 0

    def length(self):
        """获取顺序表的当前长度"""
        return self.curlen

    def get(self,index):
        """读取第index个元素"""
        if index < self.length():
            return self.listitem[index]
        else:
            return False

    def insert(self,data,index):
        """在index序列处插入数据data"""
        if index > self.maxsize or index < 0:
            return False
        elif self.curlen == self.maxsize:
            return False
        elif index <= self.maxsize and index >= self.curlen:
            self.listitem[index] = data
            self.curlen += 1
        else:
            for i in range(self.curlen-1,index-1,-1):
                self.listitem[i+1] = self.listitem[i]
            self.listitem[index] = data
            self.curlen += 1

    def remove(self,index):
        """删除index序列的元素"""
        if index >= self.curlen or index < 0:
            return False
        else:
            for i in range(index,self.curlen-1):
                self.listitem[i] = self.listitem[i+1]
            self.listitem[self.curlen-1] = None
            self.curlen -= 1


    def display(self):
        """展示顺序表"""
        print("顺序表:",self.listitem)

if __name__ == "__main__":
    """主函数测试顺序表类"""
    list = sqlist(3)
    list.insert(1,0)
    list.insert(2,1)
    list.insert(3,0)
    list.display()
    print("顺序表的当前长度为:",list.length())
    list.remove(1)
    list.display()
    print("顺序表的当前长度为:", list.length())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
'
运行

1.2.2 主函数测试运行结果

运行结果
各实例函数均运行正常,顺序表类创建成功!

二、单链表

1.1 定义与特点

定义:采用链式存储方式存储的线性表称为链表。单链表是指结点中只包含一个指针域的链表。
特点:单链表的结点存储空间是在插入和删除过程中动态申请和释放的,不需要预先分配,从而避免了顺序表顺序表应存储空间不足需要扩充空间和复制元素的过程,也避免了顺序表因容量空间过大而造成的内存资源浪费的问题,提高了运行效率存储空间的利用率。

1.2 创建单链表

首先创建一个结点类:

class Node:
    """节点"""
    def __init__(self,data):
        self.data = data
        self.next = None
  • 1
  • 2
  • 3
  • 4
  • 5
'
运行

接着创建一个单链表类:

class singlelinkedlist:
    """单链表"""
    def __init__(self):
        self.head = None

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

    def length(self):
        """获取链表长度"""
        cur = self.head
        count = 0
        while cur is not None:
            count += 1
            cur = cur.next  ###next无法理解
        return count

    def add_fist(self,data):
        """链表头部添加元素"""
        node = Node(data)
        node.next = self.head
        self.head = node
    def append(self,data):
        """链表尾部添加元素"""
        node = Node(data)
        if self.is_empty():
            self.head = node
        else:
            cur = self.head
            while cur.next is not None:
                cur = cur.next
            cur.next = node
    def insert(self,index,data):
        """
        在中间插入元素
        两种特殊情况:开头和结尾
        :param index 索引,插入位置
        :param data:插入数据
        :return:
        """
        node = Node(data)
        if index < 0 or index >self.length():
            return False
        elif index == 0:
            self.add_fist()
        elif index == self.length():
            self.append()
        else:
            cur = self.head
            count = 0
            while count < index -1:
                cur = cur.next
                count += 1
            node.next = cur.next
            cur.next = node

    def remove(self,data):
        """删除结点:
        1.头节点
        2.其余节点
        """
        cur = self.head #指针指向的节点
        pre = None #指针指向节点的前一个
        if self.head == data:
            self.head.next = self.head
        else :
            while cur.data is not data:
                pre = cur
                cur = cur.next
            pre.next = cur.next

    def get(self,index):
        """读取并返回第index个数据元素"""
        cur = self.head
        if index < 0 or index >= self.length():
            return False
        i = 0
        while i < index and cur is not None:
            cur = cur.next
            i += 1
        return cur.data

    def search_node_is_exist(self,data):
        """查找指定节点是否存在"""
        cur = self.head
        while cur is not None:
            if cur.data ==data:
                return True
            else:
                cur = cur.next
        return False

    def traversal(self):
        """遍历并打印整个链表"""
        cur = self.head
        while cur is not None:
            print(cur.data)
            cur = cur.next
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
'
运行

主函数测试一下单链表类的函数功能是否正常:

if __name__ == '__main__':
    """主函数测试"""
    lists = singlelinkedlist()
    lists.add_fist(2)
    lists.add_fist(1)
    lists.append(4)
    lists.insert(2, 3)
    lists.traversal()
    print(lists.is_empty())
    print(lists.length())
    lists.remove(3)
    print(lists.search_node_is_exist(4))
    lists.traversal()
    lists.get(0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

运行结果:
在这里插入图片描述
结果运行正常,单链表类创建成功!

三、使用顺序和链式存储的线性表解决约瑟夫(Josephus)问题

3.1 题目

在这里插入图片描述在这里插入图片描述

3.2 解题思路与代码分析

以上两种线性表分别保存在两个py文件里,这里我们新建一个py文件,再导入刚才创建的顺序表类和单链表类就能直接用啦!
题目要求包含两个静态方法,我们就创建一个类来放置这些静态方法,这里我命名为josephus,再定义两个静态方法,sequence用于顺序表解决Josephus问题,link用于单链表解决Josephus问题。传入参数如题目要求,都为(n,m,s),n代表开始报数时的人数,m代表下一次出列时的人所报出的数字序号,s为最开始报数的那人编号。

from singlelinkedlist import Node,singlelinkedlist
from sqlist import sqlist

class josephus:
    def __init__(self):
        self.name = "小熊猫爱吃红苹果还是青苹果呢?"
    @staticmethod
    def sequence(n,m,s):
    	"""顺序表"""
    @staticmethod
    def link(n,m,s):
		"""单链表"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接下来我们具体分析顺序表和单链表:
顺序表:
在这个函数里,我们创建了顺序表sqlist的实例对象list,其初始元素都为None,通过while循环为该顺序表赋值,加入判断语句if,当顺序表元素为None并且报数等于给定值m时才会进行赋值,若元素不为None,即已赋值状态,则会跳过,不会重复赋值,当所有元素都不为None时结束循环,停止赋值。为判断报数是否等于给定值,加入变量times作为报数计数器,此外加入变量value作为出列次序计数器,将value赋值给顺序表,则顺序表元素索引+1即代表报数人号码,顺序表元素值代表第几个出列,于是,只要引入列表c,按照顺序表元素值从小到大存储其对应元素序列,就能得到题目要求的出列次序。

    @staticmethod
    def sequence(n,m,s):
        """顺序表"""
        list = sqlist(n)

        c = [] #出列顺序暂存列表
        times = 0  # 报数计数器
        value = 0  # 出列次序计数器
        index = s-1 #从s-1开始数
        while True:
            if list.listitem[index] is None:
                times += 1
                if times == m:
                    times = 0
                    value += 1
                    list.listitem[index] = value
                    c.append(index + 1)
            index += 1
            if index >= n:
                index = 0
            # 设置循环终止条件
            for j in range(n):
                if list.listitem[j] is None:
                    b = False
                    break
                else:
                    b = True
            if b:
                break
        print("顺序表的出列次序是:", c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

单链表
在这个函数里,我们创建了单链表singlelinkedlist的实例对象chain,并用for循环和singlelinkedlist类定义的append函数为chain单链表赋值,得到初始节点数据分别为1,2,…….,n。接着,我们尝试获取出列次序,为了不改变节点的数据值,我们引入中间数组a[]和c[],其中数组a赋值为从0到n-1的整数,重复顺序表解决Josephus的操作,当报数计数器times等于m且元素不为None时,为该元素赋值None,并将对应的单链表数据赋值给数组c,当数组a全部为None时,停止循环和赋值,打印数组c,最终得到题目要求的出列次序。

    @staticmethod
    def link(n,m,s):
        """单链表"""
        """创建长度为n的单链表"""
        chain = singlelinkedlist()
        for i in range(n):
            chain.append(i+1)
        """获取出列次序"""
        a = []
        for j in range(n):
            a.append(j)
        c = []
        times = 0
        index = s - 1
        while True:
            if a[index] is not None:
                times += 1
                if times == m:
                    c.append(chain.get(a[index]))
                    times = 0
                    a[index] = None
            index += 1
            if index >= n:
                index = 0
            #终止条件
            for j in range(n):
                if a[j] is not None:
                    b = False
                    break
                else:
                    b = True
            if b:
                break
        print("单链表的出列次序是:",c)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

​最后用主函数测试一下,看看能否正常运行:

if __name__ == "__main__":
    """主函数测试"""
    josephus.sequence(8,4,2)
    josephus.link(8,4,2)
  • 1
  • 2
  • 3
  • 4

运行结果:
在这里插入图片描述
运行成功!你真棒!奖励一颗红彤彤的大苹果!

3.3 完整代码

from singlelinkedlist import Node,singlelinkedlist
from sqlist import sqlist

class josephus:
    def __init__(self):
        self.name = "小熊猫爱吃红苹果还是青苹果呢?"

    @staticmethod
    def sequence(n,m,s):
        """顺序表"""
        list = sqlist(n)

        c = [] #出列顺序暂存列表
        times = 0  # 报数计数器
        value = 0  # 出列次序计数器
        index = s-1 #从s-1开始数
        while True:
            if list.listitem[index] is None:
                times += 1
                if times == m:
                    times = 0
                    value += 1
                    list.listitem[index] = value
                    c.append(index + 1)
            index += 1
            if index >= n:
                index = 0
            # 设置循环终止条件
            for j in range(n):
                if list.listitem[j] is None:
                    b = False
                    break
                else:
                    b = True
            if b:
                break
        print("顺序表的出列次序是:", c)

    @staticmethod
    def link(n,m,s):
        """单链表"""
        """创建长度为n的单链表"""
        chain = singlelinkedlist()
        for i in range(n):
            chain.append(i+1)
        """获取出列次序"""
        a = []
        for j in range(n):
            a.append(j)
        c = []
        times = 0
        index = s - 1
        while True:
            if a[index] is not None:
                times += 1
                if times == m:
                    c.append(chain.get(a[index]))
                    times = 0
                    a[index] = None
            index += 1
            if index >= n:
                index = 0
            #终止条件
            for j in range(n):
                if a[j] is not None:
                    b = False
                    break
                else:
                    b = True
            if b:
                break
        print("单链表的出列次序是:",c)


if __name__ == "__main__":
    """主函数测试"""
    josephus.sequence(8,4,2)
    josephus.link(8,4,2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/802974
推荐阅读
相关标签
  

闽ICP备14008679号