目录 1.学习链表的作用:
学习链表的作用:
链表是数据结构中最最最最基础的一个模块,如果不学习链表,后续更复杂的数据结构将难以下手。
所谓基础不牢地动山摇,因此学习链表很很很关键!如果你想成为编程高手的话,否则当我没说。
------------------------------------------------------开始进入主题------------------------------------------------------
话不多说,先上代码。如果你已经看懂了可跳过这篇文章。
class Node(object): #定义节点
def __init__(self,elem):
self.elem=elem #指向的是当前数据
self.next=None #指向的是下一个数据
class SingLeLinkList(object):
def __init__(self,node=None):
self._head=node
def is_empty(self):
return self._head is None
#这里有往后移动的操作
def length(self):#要有一个游标,指向当前的位置 !!!
cur=self._head #用cur来移动遍历节点
count=0
while cur!=None:
count=count+1
cur=cur.next
return count
def travel(self):
cur=self._head
while cur!=None:
print(cur.elem)
cur=cur.next
def append(self,item):
node=Node(item)
if self.is_empty():
self._head=node
else:
cur=self._head
while cur.next!=None:
cur=cur.next
cur.next=node
def add(self,item):
node=Node(item)
node.next=self._head #当前挂的节点指向了原有列表的头结点
self._head=node #原有的头结点指向了当前添加的元素
def insert(self,pos,item):
if pos<=0:
self.add(item)
elif pos>=self.length()-1:
self.append(item)
else:
pre=self._head
count=0
while count<pos-1:
pre=pre.next
count+=1
#当退出循环,pre指向pos-1的位置
node=Node(item)
node.next=pre.next
pre.next=node
def search(self,item):
cur=self._head
while cur!=None:
if cur.elem==item:
return True
else:
cur=cur.next
return False
def remove(self,item):
cur=self._head
pre=None
while cur!=None:
if cur.elem==item:
#先判断是不是头结点
if cur==self._head:
self._head=cur.next
else:
pre.next=cur.next
break
else:
pre=cur
cur=cur.next
if __name__=='__main__':
li=SingLeLinkList()
print(li.length())
li.append(1)
li.append(2)
li.add(8)
li.insert(1,99)
li.travel()
看不懂吧?看不懂就对了,你要能看得懂显得我多没价值。话不多说先上思想。
判断是不是陷入了代码误区
a.你先看的是遍历函数 b.你先看的是添加节点函数
答案显而易见,先看添加节点函数。
解释:先创建链表的节点,把它们连接起来,才能够实现从上一个节点指向下一个节点的功能。
如图:
具体的创建链表代码:
def add(self,item):
node=Node(item) #创建一个新的节点。节点含有elem 和 next 属性。
#注意!next是单独的一个属性,它在内存里面也有空间。
node.next=self._head #当前创建的节点 的 next属性(有空间)指向了原有列表的头结点。
self._head=node #原有的头结点指向了当前添加的元素。(添加两个属性 一个是elem 一个是next)
往后看 ! !!
具体的遍历链表的代码:
def travel(self):
cur=self._head # 用于表示 当前遍历的 节点(含有两个属性一个elem,一个next)
while cur!=None: #当前遍历的节点不为空 说明有节点
print(cur.elem) #打印当前遍历的elem属性
cur=cur.next #因为cur的next已经连接的有下一个节点的elem属性
#初学者不清楚cur.next是怎么指向下一个节点的,其实在创建的add方法中已经实现了next指下一个节点的方法
这里是简化的四个步骤,第一步cur先指向头结点,然后向后遍历,继续重复前面的操作,直到指向最后一个节点。当指到的节点为None时,结束遍历。
具体的链表末尾加入链表的代码:
这个时候cur.next指向空的,添加新的节点进去:
代码:
def append(self,item):
node=Node(item) #先创建一个节点,有两个属性
if self.is_empty(): #如果为空就直接从头结点(为空)加入新的节点
self._head=node
else: #如果链表有其它节点
cur=self._head # 用于标记当前的节点
while cur.next!=None:
#这里为什么是cur.next呢,因为当cur.next指向空后,我们才把新的节点连接到next上面去
cur=cur.next #不断地遍历,直到找到下一个节点为空的时候
cur.next=node #此时跳出循环就是空的情况,直接加入新的节点
相信看到这里你已经明白了链表的基本原理了。试着看看插入和寻找已经删除节点的方法。
这里上代码纯享版:
def insert(self, pos, item):
"""
在链表的指定位置插入一个元素。
如果位置小于等于0,则在链表头部插入;
如果位置大于等于链表长度减1,则在链表尾部插入;
否则,在指定位置插入。
参数:
pos -- 插入的位置
item -- 要插入的元素
"""
if pos <= 0:
self.add(item) # 这里假设 add 方法是在链表头部插入的
elif pos >= self.length() - 1:
self.append(item) # 这里假设 append 方法是在链表尾部插入的
else:
pre = self._head # pre 指针用于遍历链表,找到插入位置的前一个节点
count = 0
while count < pos - 1: # 循环直到 pre 指向 pos-1 的位置
pre = pre.next
count += 1
# 当退出循环,pre 指向 pos-1 的位置
node = Node(item) # 创建一个新节点
node.next = pre.next # 将新节点的 next 指向 pre 原本指向的下一个节点
pre.next = node # 将 pre 的 next 指向新节点,完成插入
def search(self, item):
"""
在链表中搜索指定的元素。
参数:
item -- 要搜索的元素
返回:
如果找到元素,则返回 True;否则返回 False。
"""
cur = self._head # cur 指针用于遍历链表
while cur != None: # 当 cur 不为空时,继续遍历
if cur.elem == item: # 如果当前节点的元素等于要搜索的元素
return True
else:
cur = cur.next # 移动到下一个节点
return False # 如果遍历完整个链表都没有找到,则返回 False
def remove(self, item):
"""
从链表中删除指定的元素。
参数:
item -- 要删除的元素
注意:这个方法没有返回值,因为它只是修改了链表。
"""
cur = self._head # cur 指针用于遍历链表
pre = None # pre 指针用于记录当前节点的前一个节点
while cur != None:
if cur.elem == item: # 如果当前节点的元素等于要删除的元素
# 先判断是不是头结点
if cur == self._head:
self._head = cur.next # 如果是头结点,则将头结点指向下一个节点
else:
pre.next = cur.next # 否则,将 pre 的 next 指向 cur 的下一个节点,跳过 cur
break # 跳出循环
else:
pre = cur # 移动 pre 和 cur 到下一个节点
cur = cur.next
最后来喝一口鸡汤吧^-^:
生活真象这杯浓酒,不经三番五次的提炼呵,就不会这样可口! —— 郭小川