数据结构之链表(Linked list)
1, 无序链表(Unordered linked list)
链表是有若干个数据节点依次链接成的数据结构,如下图所示,每一个数据节点包括包括数据和一个指向下一节点的指针。(python中的list就是由链表来实现的)
无序链表操作:
Llist = UnorderedList() #创建无序链表
add(item) #向链表中加入item(首部加入)
remove(item) #从链表中移除item
search(item) #从链表中搜索item
pop() #从链表末尾移除节点
append() #从链表末尾加入节点
pop(pos) #从链表指定位置移除节点
insert(pos, item) #从链表指定位置加入节点
index(item) #返回item在链表中的位置
size() #返回链表大小
isEmpty() #返回链表是否为空
python实现无序链表
定义了Node类和UnorderedList类,代码如下:
#coding:utf-8 class Node(object):
def __init__(self,data):
self.data = data
self.next = None
def getData(self):
return self.data def getNext(self):
return self.next def setData(self,newData):
self.data=newData def setNext(self,newNext):
self.next = newNext class UnorderedList(object):
def __init__(self):
self.head=None def add(self,item):
temp = Node(item)
temp.setNext(self.head)
self.head=temp def remove(self,item): #未考虑item不存在链表中的情况,考虑时参见下面有序列表中remove方法
previous = None
current = self.head
found = False
if current:
while not found:
if current.getData()==item:
found = True
else:
previous = current
current = current.getNext()
if previous==None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
return found def search(self,item):
current = self.head
found = False
while current!=None and (not found):
if current.getData()==item:
found = True
return current
else:
current = current.getNext()
return found def pop(self):
previous = None
current = self.head
if current:
while current.getNext()!=None:
previous = current
current = current.getNext()
if previous==None:
self.head=None
else:
previous.setNext(None)
else:
raise IndexError("pop from empty unorderedList")
return current.getData() def append(self,item):
temp = Node(item)
current = self.head
previous = None
while current!=None:
previous = current
current = current.getNext()
if previous==None:
self.head=temp
else:
previous.setNext(temp) def index(self,item):
count = 0
current =self.head
while current and (current.getData()!=item):
count = count+1
current = current.getNext()
if count and (count<self.size()):
return count
else:
raise ValueError("%s is not in UnorderedList"%item) def size(self):
count = 0
current = self.head
while current!=None:
count += 1
current = current.getNext()
return count def isEmpty(self):
return self.head==None u = UnorderedList()
u.append(3)
u.append(2)
u.append(6)
#print u.index(6), u.index(7)
print u.size(),u.pop()
print u.size(),u.pop()
print u.size(),u.pop()
链表排序
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))) 利用归并排序对链表排序
def sort_list(head):
if head==None or head.next==None:
return head
left = head
mid = get_mid(head)
right = mid.next
mid.next=None
return merge(sort_list(left),sort_list(right)) def merge(left, right):
node = ListNode()
temp = node
while left and right:
if left.data>=right.data:
temp.next = right
right = right.next
else:
temp.next = left
left = left.next
temp = temp.next
if left:
temp.next = left
if right:
temp.next = right
return node.next def get_mid(node):
if node==None:
return node
slow = node
fast = node
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
return slow
l1.traverse()
sort_list(l1)
l1.traverse()
print("*"*)
l2.traverse()
sort_list(l2)
l2.traverse()
归并排序
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))) #利用堆来排序
def sort_list2(head):
if head==None:
return head
temp = head
import heapq
hq = []
while temp:
heapq.heappush(hq,temp.data)
temp = temp.next
head = ListNode(heapq.heappop(hq))
prev = head
while hq:
current = ListNode(heapq.heappop(hq))
prev.next = current
prev = prev.next l1.traverse()
sort_list2(l1)
l1.traverse()
print("*"*)
l2.traverse()
sort_list2(l2)
l2.traverse()
堆排序
链表倒转
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))) def reverse(head):
prev = head
cur = head.next
prev.next = None
while cur:
temp = cur.next
cur.next = prev
prev = cur
cur = temp
return prev
l1.traverse()
r = reverse(l1)
print("="*)
r.traverse()
单链表倒转
#链表翻转。给出一个链表和一个数k,比如,链表为1→→→→→,k=,则翻转后2→→→→→,若k=,翻转后3→→→→→,若k=,翻转后4→→→→→,用程序实现。 class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode()))))) def reverse(head):
prev = head
cur = head.next
prev.next = None
while cur:
temp = cur.next
cur.next = prev
prev = cur
cur = temp
return prev,head
def reverse_linkedlist(head,k):
temp = head
for i in range(k-):
temp = temp.next
if temp==None:
return None
mid = temp.next
temp.next=None
head1,end1 = reverse(head)
head2,end2 = reverse(mid)
end1.next = head2
return head1 l2= reverse_linkedlist(l1,)
l2.traverse()
复杂链表倒转
判断链表是否有环,并返回环入口点,计算环长度
(1)题目描述:输入一个单向链表,判断链表是否有环?
分析:通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode()))) #在链表中构造环路
def cycle_list(l1):
first = l1
temp = first
for i in range(): #向后移动三次,即将20作为入环节点
temp = temp.next
while first.next:
first = first.next
first.next = temp
return l1
l3 = cycle_list(l1)
#l3.traverse() #检查是否存在环路
def check_cycle(head):
slow = fast = head
while fast!=None and fast.next!=None:
fast = fast.next.next
slow = slow.next
if slow is fast:
return True
return False
print(check_cycle(l2)) #False
print(check_cycle(l3)) #True
判断是否有环
(2)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,如何找到环的入口点?
解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当 p1 和 p2 再次相遇的时候,就是环路的入口了。
为什么?:假定起点到环入口点的距离为 a,p1 和 p2 的相交点M与环入口点的距离为b,环路的周长为L,当 p1 和 p2 第一次相遇的时候,假定 p1 走了 n 步。那么有:
p1走的路径: a+b = n
;
p2走的路径: a+b+k*L = 2*n
; p2 比 p1 多走了k圈环路,总路程是p1的2倍
根据上述公式可以得到 k*L=a+b=n
显然,如果从相遇点M开始,p1 再走 n 步的话,还可以再回到相遇点,同时p2从头开始走的话,经过n步,也会达到相遇点M。显然在这个步骤当中 p1 和 p2 只有前 a 步走的路径不同,所以当 p1 和 p2 再次重合的时候,必然是在链表的环路入口点上。因为p1和p2点同时到达相遇点M,若都往后倒退b步则为环入口点,则第一次重合点必然是环路入口点。
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode()))) #在链表中构造环路
def cycle_list(l1):
first = l1
temp = first
for i in range(): #向后移动三次,即将20作为入环节点
temp = temp.next
while first.next:
first = first.next
first.next = temp
return l1
l3 = cycle_list(l1)
#l3.traverse() #返回入环点
def check_cycle_entrance(head):
slow = fast = head
found_cycle = False
while fast!=None and fast.next!=None and not found_cycle:
fast = fast.next.next
slow = slow.next
if slow is fast: #链表有环路
found_cycle=True
if found_cycle:
fast = head #快指针从头结点开始,一次走一步
while fast!=slow:
fast = fast.next
slow = slow.next
return fast
else:
return None
cycle_node = check_cycle_entrance(l3)
print(cycle_node.data)
cycle_node = check_cycle_entrance(l2)
print(cycle_node)
返回入环点
(3)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算环的长度?
解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,从相遇点继续走,那么当 p1 和 p2 再次相遇的时候,p1走过的长度即为环长度。
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode()))) #在链表中构造环路
def cycle_list(l1):
first = l1
temp = first
for i in range(): #向后移动三次,即将20作为入环节点
temp = temp.next
while first.next:
first = first.next
first.next = temp
return l1
l3 = cycle_list(l1)
#l3.traverse() #计算环路长度
def count_cycle_length(head):
slow = fast = head
found_cycle = False
while fast!=None and fast.next!=None and not found_cycle:
fast = fast.next.next
slow = slow.next
if slow is fast: #链表有环路
found_cycle=True
if found_cycle:
count =
fast = fast.next.next
slow = slow.next
while fast!=slow: #第二次相遇
fast = fast.next.next
slow = slow.next
count = count+
return count
else:
return None
cycle_length = count_cycle_length(l3)
print(cycle_length)
计算环长度
(4)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算链表长度?
解题思路:计算出第(2)题中a和第(3)题中的环路长,两者之和即为链表长度
判断链表的公共交点
题目描述:给出两个单向链表的头指针(如下图所示),求链表的交点
解题思路:求出两链表的长度,长链表先走,然后逐个比较两个链表的值,第一个相等的值即为交点。(若只要判断是否相交,只需判断尾节点是否相等)
class ListNode(object):
def __init__(self,data,next=None):
self.data = data
self.next = next
def traverse(self):
temp = self
while temp!=None:
print temp.data
temp = temp.next l1 = ListNode(,ListNode(,ListNode(,ListNode(,ListNode(,ListNode())))))
l2 = ListNode(,ListNode(,ListNode(,ListNode()))) #判断链表交点
def linkedlist_node(l1,l2):
head1 = l1
head2 = l2
length1=length2=
while head1:
length1 = length1+
head1 = head1.next
while head2:
length2 = length2+
head2 = head2.next
if length1>length2: #长链表先走
for i in range(length1-length2):
l1 = l1.next
else:
for i in range(length2-length1):
l2 = l2.next
while l1!=None and l2!=None:
if l1.data = l2.data: #应该是l1==l2(或l1 is l2),这里使用值代替了,方便看执行结果
return l1.data
l1 = l1.next
l2 = l2.next
return None
print(linkedlist_node(l1,l2))
链表交点
2,有序列表(Ordered List)
有序列表和无序列表结构相同,只是列表中的数据按顺序排列(升序或降序),其常用操作也基本相同。
常用操作
Llist = OrderedList()
add(item)
remove(item)
search(item)
pop()
pop(pos)
index(item)
size()
isEmpty()
python 实现有序列表
pop(), index(item), size()和isEmpty()方法和UnorderedList相同,add(item), search(item)和remove(item)代码如下所示:
class OrderedList(object):
def __init__(self):
self.head = None def add(self,item):
previous = None
current = self.head
while current and (item > current.getData()):
previous = current
current = current.getNext()
temp = Node(item)
if previous == None:
temp.setNext(self.head)
self.head=temp
else:
previous.setNext(temp)
temp.setNext(current) def search(self,item):
current = self.head
found = False
stop = False
while current!=None and (not found) and (not stop):
if current.getNext()==item:
found =True
else:
if current.getData()<item:
current = current.getNext()
else:
stop = True
return found def remove(self,item):
previous = None
current = self.head
while current and (item!=current.getData()):
previous = current
current = current.getNext()
if current!=None:
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
else: # self.head=None或者item不存在链表中
raise ValueError('%s item is not in the OrderedList'%item)
http://wuchong.me/blog/2014/03/25/interview-link-questions/
数据结构之链表(Linked list)的更多相关文章
- 数据结构之链表(Linked list)
说明:如果仔细阅读完全文后,可能感觉有些不统一,这里先说明下原因. 链表尾引用不统一:在介绍单链表时,只有一个链表首部的引用(head) 指向第一个节点.你看到后面关于双链表及循环列表时,除了指向第一 ...
- 算法与数据结构基础 - 链表(Linked List)
链表基础 链表(Linked List)相比数组(Array),物理存储上非连续.不支持O(1)时间按索引存取:但链表也有其优点,灵活的内存管理.允许在链表任意位置上插入和删除节点.单向链表结构一般如 ...
- 数据结构-单链表(Linked List)
#include <stdio.h> #include <stdlib.h> #define LIST_INIT_SIZE 10 #define LISTINCREMENT 1 ...
- 数据结构与算法 —— 链表linked list(01)
链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...
- Java数据结构之链表(Linked List)
1.链表(Linked List)介绍 链表是有序的列表,但是它在内存存储结构如下: 2.特点: 链表是以节点的方式来存储,是链式存储 每个节点包含 data 域, next 域:指向下一个节点. 链 ...
- Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现
单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...
- 链表Linked List
链表Linked List 1. 链表 数组是一种顺序表,index与value之间是一种顺序映射,以O(1)O(1)的复杂度访问数据元素.但是,若要在表的中间部分插入(或删除)某一个元素时,需要将后 ...
- 数据结构之链表(LinkedList)(一)
链表(Linked List)介绍 链表是有序的列表,但是它在内存中是存储如下 1)链表是以节点方式存储的,是链式存储 2)每个节点包含data域(value),next域,指向下一个节点 3)各个节 ...
- 学习javascript数据结构(二)——链表
前言 人生总是直向前行走,从不留下什么. 原文地址:学习javascript数据结构(二)--链表 博主博客地址:Damonare的个人博客 正文 链表简介 上一篇博客-学习javascript数据结 ...
- linux内核数据结构之链表
linux内核数据结构之链表 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...
随机推荐
- Centos7.7安装expect命令工具
简单介绍 expect是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预.说白了,expect就是一套用来实现自动交互功能的软件. 在实际工作中,我们运行命令.脚本或程序时,这些命令.脚本 ...
- JAVA对ArrayList排序
ava如何对ArrayList中对象按照该对象某属性排序 增加排序功能,打印时:输出学生对象的时候,需要先按照年龄排序,如果年龄相同,则按照姓名排序,如果姓名也相同,则按照学号排序. Code hig ...
- 3.第一个MyBatis程序_进化
1.使用工具类 将SqlSession的获取 封装成一个工具 private static SqlSession session = null; static { try { InputStream ...
- 4.AOP原理模拟
AOP Aspect-Oriented-Programming 面向切面编程 a)是对面向对象的思维方式的有力补充 好处:可以动态的添加和删除在切面上的逻辑而不影响原来的执行代码 a)Fil ...
- 利用django 实现个人博客 全记录(二)
上一篇文章已经把基础环境搭建好了 一 创建app D:\学习\python3.7.3\python manage.py startapp blog 修改 博客的 models.py ) ) def ...
- 工作总结 页面 ActionResult / JsonResult 将对象以 Json() 返回
其实都不用在页面上序列化 打印 都不需要在页面上 像这样 var ajaxResult = eval("(" + data + ")"); 序列化为对象 ...
- go语言字符串函数小结
拼接字符串 func Join(a []string, sep string) string, 拼接字符串,将一个[]string的切片通过分隔符,拼接成一个字符串,类似于PHP的implode() ...
- opencv读取图像python和c++版本的结果不同
问题: 在读取同一张图像时,python读取的结果和c++读取的结果差异较大,测试图像中最大误差达到16. 原因: python的opencv采用的是4.1.1,c++采用的是3.1.0,在解析JPE ...
- 并发编程: 生产消费模型、死锁与Rlock、线程、守护线程、信号量、锁
一.守护进程 二.互斥锁 三.抢票 四.进程间通讯 五.进程间通讯2 一.守护进程 """ 进程间通讯的另一种方式 使用queue queue 队列 队列的特点: 先进的 ...
- vim文本编辑及文件查找应用4
linux系统上的特殊权限 : 特殊权限有:SUID,SGID,STICKY 安全上下文: 1.进程以其发起者的身份运行:进程对文件的访问权限,取决于发此进程的用户的权限:进程是发起些进程用户的代理, ...