一、什么是链表?
链表是一种动态数据结构,它是用一组任意的存储单位存放数据元素。链表中的每一个元素成为”结点”,每个结点都是由数据域和指针域组成。它与数组有如下不同点:
- 数组需要预先定义大小,无法适应数据动态地增减,数据小于定义长度会浪费内存,超过则会无法插入。而链表是动态增删,可以随意增加。
- 数组对于元素查找很方便,直接get索引即可。链表获取元素则需要从头开始寻找,但是对于增删元素,直接修改结点指向即可,相对于数组更简单。
- 数组从栈中分配空间,链表中堆中分配空间,自由度大当管理麻烦。
二、链表基本方法实现(python)
1、初始化链表
"""结点类"""
class Node(object):
def __init__(self, x):
self.x = x
self.next = None
def __init__(self):
"""初始化链表"""
self.head = None
2、获取链表长度
def __len__(self):
pre = self.head
length = 0
while pre:
length += 1
pre = pre.next
return length
3、追加结点
如果head结点不存在,当前结点为head结点,否则找到尾结点,将尾结点的next指向当前结点(可以添加head和tail两个结点,就不需要寻找尾结点了)
"""追加结点"""
def append(self, x):
"""
1、head为none:head-->node
2、tail.next-->node
"""
node = Node(x)
if self.head is None:
self.head = node
else:
pre = self.head
while pre.next:
pre = pre.next
pre.next = node
4、获取结点
即判断index值的正负
def get(self, index):
index = index if index >= 0 else len(self) + index
if len(self) < index or index < 0:
return None
pre = self.head
while index:
pre = pre.next
index -= 1
return pre
5、设置结点
找到当前结点赋值即可
"""设置结点"""
def set(self, index, x):
node = self.get(index)
if node:
node.x = x
return node
6、插入结点
插入结点要找到插入位置的前一个结点,然后将前一结点的next指向当前结点,当前结点的next指向下一结点。
"""插入结点"""
def insert(self, index, x):
"""
1、index 插入结点位置 包括正负数
2、找到 index-1 --> pre_node 的结点
3、 pre_node.next -->node
node.next-->pre_node.next.next
4、head
"""
node = Node(x)
if abs(index + 1) > len(self):
return False
index = index in index >= 0 else len(self) + index + 1
if index == 0:
node.next = self.head
self.head = node
else:
pre = self.get(index - 1)
if pre:
next = pre.next
pre.next = node
node.next = next
else:
return Fasle
return node
7、删除结点
删除结点,也要区分索引正负。找到当前结点前一个pre_node和后一个next_node, 将pre_node.next–>next_node 即可
"""删除某个元素"""
def del(self, index):
f = index in index > 0 else abs(index + 1)
if len(self) <= f:
return False
pre = self.head
index = index if index >= 0 else len(self) + index
prep = None
while index:
prep = pre
pre = pre.next
index -= 1
if not prep:
self.head = pre.next
else:
prep.next = pre.next
return pre.x ###
8、反转链表
反转链表就是将node.next–>pre_node 递归实现即可,然后将tail 赋值为head
"""反转链表"""
def __reversed__(self):
"""
1、pre-->next 转为next-->pre
2、pre 若是head 则把pre.next--> None
3、tail-->self.head
"""
def reverse(pre_node, node):
if pre_node is self.head:
pre_node.next = None
if node:
next_node = node.next
node.next = pre_node
return reverse(node, next_node)
else:
self.head = pre_node
return reverse(self.head, self.head.next)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
prev = None
if not head:
return head
while head:
cur = head
head = head.next
cur.next = prev
prev = cur
return cur
9、判断回文链表
time:O(n) space: O(1)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
p1 = p2 = head
res = None
while p1 and p1.next:
p1 = p1.next.next
res, res.next, p2 = p2, res, p2.next
if p1:
p2 = p2.next
while res and res.val == p2.val:
res, p2 = res.next, p2.next
return not res
10、leetcode_25.按k-group反转链表的结点
比如:给定链表: 1->2->3->4->5
当 k = 2, 返回: 2->1->4->3->5
当 k = 3, 返回: 3->2->1->4->5
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseKGroup(self, head, k):
"""
:type head: ListNode
:type k: int
:rtype: ListNode
"""
dummy = jump = ListNode(0)
dummy.next = l = r = head
while True:
count = 0
while r and count < k: # use r to locate the range
r = r.next
count += 1
if count == k: # if size k satisfied, reverse the inner linked list
pre, cur = r, l
for _ in range(k):
cur.next, cur, pre = pre, cur.next, cur # standard reversing
jump.next, jump, l = pre, l, r # connect two k-groups
else:
return dummy.next