• 数据结构-链表


    一.介绍

      采用链式方式存储的线性表称为链表,链表用若干地址分散的存储单元存储数据,逻辑上相邻的数据元素在物理位置上不一定相邻

    二.单链表

      单链表是指节点中只包含一个指针域的链表,指针域中的存储着指向后继节点的指针。单链表的头指针是线性表的起始地址,是线性表中第一个数据元素的存储地址,可作为单链表的唯一标识。单链表的尾节点没有后继节点,所以其指针域值为None。

      为了操作简单,在第一个节点之前增加头节点,单链表的头指针指向头节点,头节点的数据域不存放任何数据,指针域存放指向第一个节点的指针。空单链表的头指针head为None。  

      单链表的节点的存储空间是在输入和删除过程中动态申请和释放的,不需要预先分配,从而避免了顺序表因存储空间不足需要扩充空间和复制元素的过程,避免了顺序表因容量过大造成内存资源浪费的问题,提高了运行效率和存储空间的利用率

      1.节点类描述

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

      2.单链表类描述

    class LinkList(IList):
        def __init__(self):
            self.head = Node() #构造函数初始化头节点
    
        def cerate(self,l,order):
            if order:
                self.create_tail(l)
            else:
                self.create_head(l)
        def create_tail(self,l):
            pass
        def create_head(self,l):
            pass
    
        def clear(self):
            """ 将线性表置为空表"""
            self.head.data = None
            self.head.next = None
        def isEmpty(self):
            """判断线性表是否为空"""
            return self.head.next == None
    
        def length(self):
            """返回线性表的长度"""
            p = self.head.next
            length = 0
            while p is not None:
                p = p.next
                length += 1
            return length
        def get(self,i):
            """读取并返回线性表中的第i个元素"""
          pass
           
        def insert(self,i,x):
            """(带头节点)的插入x为第i个元素"""
            pass
    
        def remove(self,i):
            """删除第i个元素"""
            pass
    
        def indexOf(self,x):
            """返回元素x首次出现的位序号"""
            pass
    
        def display(self):
            """输出线性表中各个数据的元素的值"""
            p = self.head.next
            while p is not None:
                print(p.data,end=' ')
                p = p.next

      3.单链表的基本操作的实现

      3.1.查找操作

      (1)位序查找get(i)返回线性表中第i 个节点设的数据域的值

      def get(self,i):
            """读取并返回线性表中的第i个元素"""
            p = self.head.next #p指向单链表的首节点
            j = 0
            #从首节点开始向后查找,直到p指向第i个节点
            while j < i and p is not None:
                p = p.next
                j += 1
            if j > i or p is not None:
                raise Exception(""+i+"个元素不存在")
            return p.data

      (2)按值查找

      def indexOf(self,x):
            """返回元素x首次出现的位序号"""
            p = self.head.next
            j = 0
            while p is not None and not (p.data == x):
                p = p.next
                j += 1
            if p is not None:
                return j
            else:
                return -1

      3.2.插入操作

      插入操作insert(i,x)是在长度为n的单链表的第i个节点之前插入数据域为x的新节点,其中0《 i 《 n ,当i=0时,在表头插入,当i=n时,在表尾插入

      步骤:

      (1)查找到插入位置的前驱节点,即第i-1个节点

      (2)创建数据域值为x的新节点

      (3)修改前驱节点的指针域为指向新节点的指针,新节点的指针域为指向原第i 个节点的指针

      带头节点的插入:

     def insert(self,i,x):
            """(带头节点)的插入x为第i个元素"""
            p = self.head
            j = -1
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p is  None:
                raise Exception("插入位置不合法")
            s  = Node(x,p.next)
            p.next = s

      不带头节点的插入:

      def insert(self,i,x):
            """(不带头节点)的插入x为第i个元素"""
            p = self.head
            j = -1
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p is not None:
                raise Exception("插入位置不合法")
            s  = Node(data=x)
            if i == 0:
                s.next = self.head
            else:
                s.next = p.next
                p.next = s

      3.3删除操作

      步骤:

      (1)判断单链表是否为空

      (2)查找待删除节点的前驱节点

      (3)修改前驱节点的指针域为待删除节点的指针域

     def remove(self,i):
            """删除第i个元素"""
            p = self.head
            j = -1
            #寻找第i个节点的前驱节点
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p.next is None:
                raise Exception("删除位置不合法")
            p.next = p.next.next

    四.实践

    1.编写一组程序,实现某班学生姓名数据的建表、展示、查找、定位、插入、删除、求表长等操作

    测试用例:

    依次输入学生姓名:赵一 钱二 孙三 李四 周五 吴六 郑七 王八

    (1)展示班级所有学生姓名和人数

    (2)查找李四在表中的位置

    (3)在王八后面加入新生郑九

    (4)删除学生赵一

    from abc import ABCMeta,abstractmethod,abstractproperty
    class IList(metaclass=ABCMeta):
        @abstractmethod
        def clear(self):
            """ 将线性表置为空表"""
            pass
        @abstractmethod
        def isEmpty(self):
            """判断线性表是否为空"""
            pass
        @abstractmethod
        def length(self):
            """返回线性表的长度"""
            pass
        @abstractmethod
        def get(self,i):
            """读取并返回线性表中第i个元素"""
            pass
        @abstractmethod
        def insert(self,i,x):
            """插入x作为第i个元素"""
            pass
        @abstractmethod
        def remove(self,i):
            """删除第i个元素"""
            pass
        @abstractmethod
        def indexOf(self,x):
            """返回元素x首次出现的位序号"""
            pass
        @abstractmethod
        def display(self):
            """输出线性表中各个数据元素的值"""
            pass
    
    class Node(object):
        def __init__(self,data=None,next=None):
            self.data = data
            self.next = next
    
    class LinkList(IList):
        def __init__(self):
            self.head = Node() #构造函数初始化头节点
    
        def cerate(self,l,order):
            if order:
                self.create_tail(l)
            else:
                self.create_head(l)
        def create_tail(self,l):
            for item in l:
                self.insert(self.length(),item)
        def create_head(self,l):
            for item in l:
                self.insert(0,item)
    
        def clear(self):
            """ 将线性表置为空表"""
            self.head.data = None
            self.head.next = None
        def isEmpty(self):
            """判断线性表是否为空"""
            return self.head.next == None
    
        def length(self):
            """返回线性表的长度"""
            p = self.head.next
            length = 0
            while p is not None:
                p = p.next
                length += 1
            return length
        def get(self,i):
            """读取并返回线性表中的第i个元素"""
            p = self.head.next #p指向单链表的首节点
            j = 0
            #从首节点开始向后查找,直到p指向第i个节点
            while j < i and p is not None:
                p = p.next
                j += 1
            if j > i or p is not None:
                raise Exception(""+i+"个元素不存在")
            return p.data
        def insert(self,i,x):
            """(带头节点)的插入x为第i个元素"""
            p = self.head
            j = -1
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p is  None:
                raise Exception("插入位置不合法")
            s  = Node(x,p.next)
            p.next = s
        def insert(self,i,x):
            """(不带头节点)的插入x为第i个元素"""
            p = self.head
            j = -1
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p is not None:
                raise Exception("插入位置不合法")
            s  = Node(data=x)
            if i == 0:
                s.next = self.head
            else:
                s.next = p.next
                p.next = s
        def remove(self,i):
            """删除第i个元素"""
            p = self.head
            j = -1
            #寻找第i个节点的前驱节点
            while p is not None and j < i-1:
                p = p.next
                j += 1
            if j > i-1 or p.next is None:
                raise Exception("删除位置不合法")
            p.next = p.next.next
    
        def indexOf(self,x):
            """返回元素x首次出现的位序号"""
            p = self.head.next
            j = 0
            while p is not None and not (p.data == x):
                p = p.next
                j += 1
            if p is not None:
                return j
            else:
                return -1
    
        def display(self):
            """输出线性表中各个数据的元素的值"""
            p = self.head.next
            while p is not None:
                print(p.data,end=' ')
                p = p.next
    View Code
    L = LinkList()
    for i in range(8):
        s = input("请输入学生名称%i:"%(i+1))
        L.insert(i,s)
    
    
    #依次输入:赵一、钱二、孙三、李四、周五、吴六、郑七、王八
    print("(1)班级学生:",end=' ')
    L.display()
    print("班级人数:",L.length())
    
    print("(2)李四在表中的位置:",L.indexOf('李四'))
    
    L.insert(L.indexOf('王八')+1,'郑九')
    print('(3)在王八的后面插入郑九后:',end=' ')
    L.display()
    print("班级人数:",L.length())
    
    L.remove(L.indexOf('赵一'))
    print('(4)删除赵一后:',end=' ')
    L.display()
    print("班级人数:",L.length())

    结果:

    请输入学生名称1:赵一
    请输入学生名称2:钱二
    请输入学生名称3:孙三
    请输入学生名称4:李四
    请输入学生名称5:周五
    请输入学生名称6:吴六
    请输入学生名称7:郑七
    请输入学生名称8:王八
    (1)班级学生: 赵一 钱二 孙三 李四 周五 吴六 郑七 王八 班级人数: 8
    (2)李四在表中的位置: 3
    (3)在王八的后面插入郑九后: 赵一 钱二 孙三 李四 周五 吴六 郑七 王八 郑九 班级人数: 9
    (4)删除赵一后: 钱二 孙三 李四 周五 吴六 郑七 王八 郑九 班级人数: 8

    2.编写一组程序,实现一元多项式的加法运算

    举例:

    p1 = 3x^3 + 5x^2 + 4x

    p2 = x^5 + 3x^2

    p1+p2 = x^5 + 3x^3 + 8x^2 + 4x

    输入:从大到小依次输入所要输入的两个一元多项式的系数和指数

    输出:输出多元式p1,p2以及两式相加的结果

    class PloyNode(object):
        def __init__(self,a,e):
            self.a = a #系数
            self.e = e#指数
    def add(p1,p2):
         L = LinkList()
         i = j = 0
        #i指针指向p1,j指针指向p2
         while i < p1.length() and j < p2.length():
             x,y = p1.get(i),p2.get(j)
             #如果此时选择的两项指数相等
             if x.e == y.e:
                 #将系数相加插入
                 L.insert(L.length(),PloyNode(x.a+y.a,x.e))
                 i += 1
                 j += 1
             elif x.e > y.e:
                 L.insert(L.length(),PloyNode(x.a,x.e))
                 i += 1
             else:
                 L.insert(L.length(),PloyNode(y.a,y.e))
                 j += 1
            #如果剩下的为p1,且p1的指数都比之前插入的小
         while i < p1.length():
             x = p1.get(i)
             #插入p1剩下的部分
             L.insert(L.length(), x)
             i += 1
    
            #如果剩下的为p2,且p2的指数都比之前插入的小
         while j < p2.length():
             y = p2.get(j)
             # 插入p2剩下的部分
             L.insert(L.length(), y)
             j += 1
    
         return L
    
    p1 = LinkList()
    p2 = LinkList()
    
    #多项式 3x^3 + 5x^2 + 4x
    p1.insert(0,PloyNode(3,3))
    p1.insert(1,PloyNode(5,2))
    p1.insert(2,PloyNode(4,1))
    
    #多项式  p2 = x^5 + 3x^2
    
    p2.insert(0,PloyNode(1,5))
    p2.insert(1,PloyNode(3,2))
    
    #相加
    L = add(p1,p2)
    for i in range(L.length()-1):
        x = L.get(i)
        #输出每一项
        print("%sx^%s + "%(x.a,x.e),end=' ')
    #最后一项没有+
    x = L.get(L.length()-1)
    print("%sx^%s"%(x.a,x.e))

    输出:

    1x^5 +  3x^3 +  8x^2 +  4x^1
  • 相关阅读:
    xml技术基础
    apue第七章学习总结
    自然连接,外部连接,内连接,左右连接的区别与介绍(转)
    apue第六章学习总结
    《深入PHP与jQuery开发》读书笔记——Chapter2
    apue第四章学习总结
    《深入PHP与jQuery开发》读书笔记——Chapter1
    我所使用的一个通用的Makefile模板
    PHP的输出缓冲区(转)
    Nginx 日志按月分割
  • 原文地址:https://www.cnblogs.com/jiangfan95/p/12191724.html
Copyright © 2020-2023  润新知