拜师教育第一阶段day3_python数据结构与算法

第三章    链表(一)

1.顺序表与链表的区别顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并是很灵活。链表结构可以充分利用计算机零散的内存空间,实现灵活的内存动态管理。链表比较适合具有大量数据,内存空间不充裕的场合。扩充时原有数据及其物理地址均未发生变化,新添加的数据只对原尾节点的next区进行操作,所以这种数据结构可以随新元素边到来边申请存储空间,所以构建时无需像顺序表一样考虑申请列表的容量大小

2.链表的定义与结构:链表是一种常见的基础数据结构,是一种线性表,它是数据存储单元与下一个节点的位置信息的集合体。链表的实现方式示意图如下:

3.若上图中所绘制的链有方向性,则称之为单链表SingleLinkList。如上图所示,它的每个节点包含两个域,一个信息域(元素域elem)和一个链接域(next:存放下一个节点的位置)。这个链接指向链表中的下一个节点,而最后一个节点(尾结点)的链接域则指向一个空值。上图中变量p指向链表的头节点(首节点)的物理地址,从p出发通过链能找到表中的任意节点。要进行链表的实现首先要考虑链表中数据的存储结构——节点,和对节点进行的相应操作。故链表是将相关数据与对数据进行的相关操作封装到一起的一种数据结构,这再次体现了面向对象的思想(可以用'类'实现)。

4.python中实现变量交换的本质:

可以通过上图了解到,变量名绑定的内存块中存储的是对象的地址,并不是存储的该对象,在a,b=b,a(右侧采用元组(20,10)的形式)中:等号右侧的元素代表该内存链接的数据,=意味着将右侧数据的地址赋值给左侧对应变量名,使其存储在变量名绑定的内存空间中。

5.节点的实现(创建类时只需要设定形式参数为数据,另外要考虑到只建一个节点的情况,此时存在的第一个节点中只有数据,链接区应指空None):

                       class  SingleNode(object):  #单链表的节点

                               def   __init__(self,elem):

                                       self.elem=elem  #elem存放数据

                                       self.next=None  #next存放下一节点的链接

6.单链表中对节点的相关操作:is_empty() 链表是否为空;length() 链表长度;travel() 遍历整个链表;add(item) 链表头部添加元素;append(item) 链表尾部添加元素;insert(pos, item) 指定位置添加元素;remove(item) 删除节点;search(item) 查找节点是否存在。将这些相关操作封装到类对象SingleLinkList中。所以在运用链表时,一定要注意有两个相关的类(节点类与链表类)。(删除操作尽量保证每个表方法的一致性:1.判断是否空链表;2.(内嵌)判断是否只有一个节点;3.(内嵌的内嵌)如果找到要删除的元素,判断该元素位置为头、尾、还是中间。)链表的翻转:可以通过新建链表,然后在从头遍历旧链表的同时,不断在新链表的头部插入元素。

7.单链表的实现:(十分重要)

# -*- coding:utf-8 -*-
class Node():
    def __init__(self,elem):
        self.elem=elem
        self.next=None
class SingleLinkList():
    def __init__(self,node=None):
        self.__head=node
    def is_empty(self):
        return self.__head==None
    def length(self):
        cur=self.__head
        num=0
        while cur!=None:
            cur=cur.next
            num+=1
        return num
    def travel(self):
        cur=self.__head
        while cur!=None:
            print(cur.elem,end='')
            cur=cur.next
        print()
    def add(self,elem):
        node=Node(elem)
        node.next=self.__head
        self.__head=node
    def append(self,elem):
        node=Node(elem)
        if self.is_empty()==True:
            self.__head = node
        else:
            cur=self.__head
            while cur.next!=None:
                cur=cur.next
            cur.next=node
    def insert(self,pos,elem):
        if pos<=0:
            return self.add()
        elif pos>self.length()-1:
            return self.append()
        else:
            node = Node(elem)
            num=0
            cur=self.__head
            while num<pos-1:
                cur=cur.next
                num+=1
            node.next=cur.next
            cur.next=node
    def search(self,elem):
        cur=self.__head
        while cur!=None:
            if cur.elem==elem:
                return True
            cur=cur.next
        return False
    def remove(self, elem):
        cur = self.__head
        pre=None
        if self.__head!=None:
            if self.__head.next!=None:
                while cur!= None:
                    if cur.elem==elem:
                        if pre==None:
                            self.__head=self.__head.next
                        elif cur.next==None:
                            pre.next=None
                        else:
                            pre.next=cur.next
                        break
                    pre=cur
                    cur=cur.next
            else:
                if self.__head.elem==elem:
                    self.__head=None
if  __name__=='__main__':#模块中独立运行主程序的语句
    ll = SingleLinkList()
    ll.add(1)
    ll.add(2)
    ll.append(3)
    ll.insert(2, 4)
    print("length:", ll.length())
    ll.travel()
    print(ll.search(3))
    print(ll.search(5))
    ll.remove(2)
    print("length:", ll.length())
    ll.travel()
    ll.remove(1)
    print("length:", ll.length())
    ll.travel()
    ll.remove(3)
    print("length:", ll.length())
    ll.travel()
    ll.remove(4)
    print("length:", ll.length())
    ll.travel()

单链表的翻转:

def reverse0(list):#外部函数
    list0=SingleLinkList()
    #list0.add(list._SingleLinkList__head.elem)
    cur=list._SingleLinkList__head
    while cur!=None:
            list0.add(cur.elem)
            cur=cur.next
    return list0

8.链表与顺序表的对比:链表失去了顺序表随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大,但对存储空间的使用要相对灵活

同样操作对应的时间复杂度为:

链表的主要耗时操作是遍历查找,删除和插入操作本身的复杂度是O(1)。顺序表查找很快,主要耗时的操作是拷贝覆盖。因为除了目标元素在尾部(对应最优时间复杂度)特殊情况,顺序表进行插入和删除时需要对操作点之后的所有元素进行前后移位操作,只能通过拷贝和覆盖的方法进行。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值