zoukankan      html  css  js  c++  java
  • 单链表,双向链表,循环链表

    数据结构:
        
        定义:
            特定的数据类型(个体)和特定的存储结构(个体的关系)
            数据如何存储在内存中
        分类:
            
            线性结构:
            数据元素之间存在一对一的线性关系。线性结构拥有两种不同的存储结构,即顺序存储结构和链式存储结构。
            
                数组与列表:顺序存储结构
                    
                    相同点:
                        需要申请一块连续的内存空间
    
                    不同点:
                        列表或者数组中的元素是如何存储的,以及两者的区别?
                            在其他语言中(C/C++)数组申请的内存空间是一定的, 比如申请10M的内存空间,如果数据超过10M会溢出,需要手动申请和释放
                            在python中不会出现溢出报错这种问题,底层做了处理会自动扩展,不需要手动申请和释放
                            
                            python:                            
                                li = [1,2,3,4,54,56,56,67,77]
                            C/C++:
                                malloc()         申请                
                                free()            释放
                            
                        列表提供了哪些最基本的操作?
                            append(), insert(), pop()等
                         
                        这些操作的时间复杂度是多少?
                            插入时间复杂度:O(n)   因为数组是连续存放的,后面的数据会后移
                            查找时间复杂度: O(1)      按照索引运算查找即可
                            
                        为啥数组(列表)的索引或者下标是从0开始?
                            减少运算的压力 查找内存位置的时候直接按照索引算即可,如果从1开始还要减一
                        
                    关于数组(列表)的优缺点:
                        优点:
                            查找快
                        
                        缺点:
                            插入慢
                            要求一块 连续 的内存空间 ***
                
                    
                链表:链式存储结构
                    插入时间复杂度:O(1)        
                    查找时间复杂度: O(n)
                    
                    链表的优点:
                        1、不需要一块连续内存空间
                        2、相对于数组来说,插入较简单
                    
                    单链表
                    双链表
                    循环链表 约瑟夫问题
                    
                    链表算法:增删改查以及总长度
                
                应用:
                    栈
                    
                    队列
                
                
            非线性结构: 
                树作为一种应用广泛的一对多非线性数据结构,不仅有数据间的指向关系,还有层级关系
                如何在内存中表示呢?
                
                树                
                
                图
                    图论
    介绍
    ###########################
    # 单链表:水浒英雄排序
    # 双向链表多一个pre
    
    class Hero:
        def __init__(self,name=None,no=None,nickname=None,pNext=None):
            self.name = name
            self.no = no
            self.nickname = nickname
            self.pNext = pNext
    
    # 直接添加到尾部
    def add(head,pnew):
        cur = head
        while cur.pNext != None:
            cur = cur.pNext
        cur.pNext = pnew
    
    # 指定位置进行添加
    def insert(head,pnew):
        cur = head
        while cur.pNext != None:
            if cur.pNext.no > pnew.no:
                break
            cur = cur.pNext
        pnew.pNext = cur.pNext
        cur.pNext = pnew
    
    # 根据no删除某个节点(英雄)
    def delHero(head,no):
        cur = head
        while cur.pNext != None:
            if cur.pNext.no == no:
                break
            cur = cur.pNext
        else:
            print("没有此元素")
        cur.pNext = cur.pNext.pNext
    
    # 查看单链表是否为空
    def is_empty(head):
        if head.pNext == None:
            return True
        else:
            return False
    
    # 计算单链表长度
    def length(head):
        cnt = 0
        cur = head
        while cur.pNext != None:
            cur = cur.pNext
            cnt += 1
        return cnt
    
    # 打印所有的单链表数据
    def getAll(head):
        cur = head
        while cur.pNext != None:
            cur = cur.pNext
            print('编号是:%s,姓名是:%s,外号:%s' %(cur.no,cur.name,cur.nickname))
    
    head = Hero()
    
    h1 = Hero('宋江',1,'及时雨')
    add(head,h1)
    
    h2 = Hero('卢俊义',2,'玉麒麟')
    add(head,h2)
    
    h3 = Hero('吴用',3,'智多星')
    add(head,h3)
    
    h4 = Hero('马波',5,'波神')
    add(head,h4)
    
    h5 = Hero('波老师',4,'波波')
    add(head,h5)
    
    print(length(head))
    getAll(head)
    ###########################
    单链表
    ###########################
    # 循环链表:解决约瑟夫问题
    # 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,
    # 数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列
    
    class Child:
        first = None
        def __init__(self,data = None,pNext = None):
            self.data = data
            self.pNext = pNext
    # 生成n个小朋友,构成循环链表
        def add(self,num):
            cur = None
            for i in range(num):
                child = Child(i+1)
                if i == 0: # 当i=0时,构成一个循环链表,指向自己,目的是:后面的好加入
                    self.first = child #first指向第一个孩子对象
                    self.first.pNext = self.first #第一个孩子的指针指向自己构成循环链表
                    cur = self.first
                else:
                    cur.pNext = child
                    child.pNext = self.first
                    cur = cur.pNext
    # 展示所有的小孩
        def showAll(self):
            cur = self.first #第一个孩子节点
            while cur.pNext != self.first: #只有末尾的节点指针指向第一个节点
                print('小孩的编号是:%s' %cur.data)
                cur=cur.pNext
            print('小孩的编号是:%s' %cur.data) #打印末尾节点的编号
    
    # 解决约瑟夫问题
        def countChild(self,m,k):
            tail = self.first #第一个孩子节点,
    
            while tail.pNext != self.first: #除了最后一个节点外,都是True
                tail = tail.pNext
            # 退出循环的话,已经到了最后一个小朋友,就在first后面
    
            # tail是用来出列之后修复循环链表,永远在first后面,执行完上面的代码就在first后面了
    
            # 从哪里开始数,first移动到报数位置,tail在first后面
            for i in range(k-1):
                self.first = self.first.pNext
                tail = tail.pNext
    
            while tail != self.first: # 退出循环的时候,圈子里面只剩一个人
                # 数2下,first、tail前移1下
                # 数3下,first、tail前移2下
                # 数m下,first、tail前移m-1下
                for i in range(m - 1):
                    self.first = self.first.pNext
                    tail = tail.pNext
                # 修复循环链表
                self.first = self.first.pNext
                tail.pNext = self.first
            print('留在圈子里面的小孩编号:%s' %tail.data)
    
    child = Child() #生成对象
    child.add(1000)  #添加100个小孩
    # child.showAll() #打印100个小孩的编号
    child.countChild(1000,300) #从编号为3的人开始,数到80的人出列
    ###########################
    循环链表
  • 相关阅读:
    Max History CodeForces
    Buy a Ticket CodeForces
    AC日记——字符串的展开 openjudge 1.7 35
    AC日记——回文子串 openjudge 1.7 34
    AC日记——判断字符串是否为回文 openjudge 1.7 33
    AC日记——行程长度编码 openjudge 1.7 32
    AC日记——字符串P型编码 openjudge 1.7 31
    AC日记——字符环 openjudge 1.7 30
    AC日记——ISBN号码 openjudge 1.7 29
    AC日记——单词倒排 1.7 28
  • 原文地址:https://www.cnblogs.com/xujinjin18/p/9972746.html
Copyright © 2011-2022 走看看