数据结构-链表

一.介绍

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

二.单链表

  单链表是指节点中只包含一个指针域的链表,指针域中的存储着指向后继节点的指针。单链表的头指针是线性表的起始地址,是线性表中第一个数据元素的存储地址,可作为单链表的唯一标识。单链表的尾节点没有后继节点,所以其指针域值为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
posted on 2020-01-14 16:07  anne199534  阅读(397)  评论(0编辑  收藏  举报