数据结构之链表(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.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该 ...
随机推荐
- ASP.NET IHttpModule IHttpHandler IHttpHandlerFactory 拦截请求
先来看看代码,拦截所有Http请求类.下面包含了两种类的集成 IHttpModule IHttpHandlerFactory using System; using System.Collection ...
- 阿里云Ubuntu下tomcat8.5配置SSL证书
环境 阿里云ubuntu(18.04)服务器 阿里云申请的域名 Tomcat8.5.7 jdk1.8 免费型SSL证书 SSL证书申请 登录阿里云的官网,登录后在菜单中选择SSL证书(应用安全) 进入 ...
- 404boom 博客闪现【不断的优化更新中。。。】
404boom 博客闪现[不断的优化更新中...] 停止本篇博文EQ继续优化,所有博文将会在标签[cnblogs_v2 ]中重新整理,待完成统一放上链接 一:Java SE相关1.Java的概述2.J ...
- Hadoop_16_MapRduce_MapTask并行度(切片)的决定机制
MapTask的并行度决定map阶段的任务处理并发度,进而影响到整个job的处理速度那么,mapTask并行实例是否越多 越好呢?其并行度又是如何决定呢?Mapper数量由输入文件的数目.大小及配置参 ...
- 解决Ubuntu下ssh无法启动
Ubuntu ssh一直无法启动. 通过 systemctl status ssh.service 查看到的错误是 Dec 16 13:35:22 iZm5eckxl2tqyka9eoe7b3Z ...
- Golang等待一组协程结束
1. 利用waitgroup import ( "log" "sync" "sync/atomic" "time" ) ...
- DATASNAP双缓存下载文件
原文链接:http://www.cnblogs.com/hnxxcxg/archive/2012/12/29/2839358.html procedure TFrmMain.btnUpdateFile ...
- shell 入门及常用命令
1.shell 是什么 shell是指一种程序, 它是和linux沟通的桥梁, 这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务, Ken Thompson 的 sh 是第一种 Un ...
- 通过轻量级终端工具Tera Term远程向linux操作系统上传war文件
通过轻量级终端工具Tera Term远程向linux操作系统上传war文件 1.打开Tera Term终端工具,并输入正确的远程机器的IP地址以及端口号: 2.输入正确的用户名和密码进入到linux操 ...
- Gym - 101492I 区间限制费用流
https://cn.vjudge.net/problem/Gym-101492I 如果用单个点代表每个区间 利用拆点来限制区间的流量的话 点是 n^2/2+m个 边是2*n^2条 但是这样会T 解法 ...