目录
1.2.3 DoublyLinkedList(Python)
一、列表
1.1 线性表的顺序存储
1.1.1 动态顺序表
线性表的顺序存储是把线性表的数据元素按逻辑次序依次存放在一组连续的存储单元中,即逻辑结构上相邻的两个数据元素存储在计算机内的物理存储位置也是相邻的,这种存储方法为整个线性表分配一整个内存块保存线性表的元素
优缺点:
优点:快速访问元素
缺点:插入元素的成本比较大
动态顺序表的结构:
属性:固定长度的数组、数组的最大长度、数组中实际元素的个数
函数:
基本功能:初始化、返回列表的长度、扩充数组的容量、是否包含某元素、将列表转为字符串输出、判断两个数组是否相等
扩展功能:在索引位置上get/set、返回指定元素的索引位置、追加、插入、删除、
1.1.2 MyArrayList(Java)
package com.ssmCombine.LeetCode;
import java.util.Iterator;
public class MyArrayList<AnyType> implements Iterable<AnyType>{
private static final int DEFAULT_CAPACITY = 10;
private int theSize;
private AnyType[] theItems;
public MyArrayList(){
doClear();
}
public void clear(){
doClear();
}
public void doClear(){
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return size() == 0;
}
public void trimToSize(){
ensureCapacity(size());
}
public AnyType get(int idx){
if (idx < 0 || idx >= size()){
throw new ArrayIndexOutOfBoundsException();
}
return theItems[idx];
}
public AnyType set(int idx, AnyType newVal){
if (idx < 0 || idx >= size()){
throw new ArrayIndexOutOfBoundsException();
}
AnyType old = theItems[idx];
theItems[idx] = newVal;
return old;
}
public void ensureCapacity(int newCapacity){
if (newCapacity < theSize)
return;
AnyType[] old = theItems;
theItems = (AnyType[]) new Object[newCapacity];
for (int i = 0; i < size(); i++) {
theItems[i] = old[i];
}
}
public void add(int idx, AnyType x){
if(theItems.length == size()){
ensureCapacity(size() * 2 + 1);
}
for (int i = theSize; i > idx; i--) {
theItems[i] = theItems[i - 1];
}
theItems[idx] = x;
theSize++;
}
public boolean add(AnyType x){
add(size(), x);
return true;
}
public AnyType remove(int idx){
AnyType removedItem = theItems[idx];
for (int i = idx; i < size() - 1; i++) {
theItems[i] = theItems[i + 1];
}
theSize--;
return removedItem;
}
public Iterator<AnyType> iterator() {
return (Iterator<AnyType>) new ArrayListIterator();
}
public class ArrayListIterator implements Iterable<AnyType>{
private int current = 0;
public boolean hasNext(){
return current < size();
}
public AnyType next(){
if(!hasNext())
throw new java.util.NoSuchElementException();
return theItems[current++];
}
public void remove(){
MyArrayList.this.remove(--current);
}
@Override
public Iterator<AnyType> iterator() {
return null;
}
}
}
1.1.3 SequentialList(Python)
class SequentialList:
def __init__(self, max_size=10):
self.items = [None] * max_size
self.num_items = 0
self.max_size = max_size
def __len__(self):
return self.num_items
def __getitem__(self, index):
if index >= 0 and index < self.num_items:
return self.items[index]
raise IndexError('SequentialList index out of range')
def __setitem__(self, index, val):
if index >= 0 and index < self.num_items:
self.items[index] = val
return
raise IndexError("SequentialList assignment index out of range")
def locate(self, item):
for i in range(self.num_items):
if self.items[i] == item:
return i
raise ValueError("{} is not in sequential list".format(item))
def __alloc(self):
new_size = (self.max_size // 4) + self.max_size + 1
new_items = [None] * new_size
for i in range(self.num_items):
new_items[i] = self.items[i]
self.items = new_items
self.max_size = new_size
def append(self, item):
if self.num_items == self.max_size:
self.__alloc()
self.items[self.num_items] = item
self.num_items += 1
def insert(self, index, item):
if self.num_items == self.max_size:
self.__alloc()
if index < self.num_items and index >= 0:
for j in range(self.num_items - 1, index - 1, -1):
self.items[j + 1] = self.items[j]
self.items[index] = item
self.num_items += 1
elif index >= self.num_items:
self.append(item)
else:
raise IndexError("SequentialList assignment index out of range")
def __delitem__(self, index):
for i in range(index, self.num_items - 1):
self.items[i] = self.items[i + 1]
self.num_items -= 1
def __str__(self):
s = '['
for i in range(self.num_items):
s += repr(self.items[i])
if i < self.num_items - 1:
s += ', '
s += ']'
return s
def __contains__(self, item):
for i in range(self.num_items):
if self.items[i] == item:
return True
return False
def __eq__(self, another):
if type(another) != type(self) or self.num_items != another.num_items:
return False
for i in range(self.num_items):
if self.items[i] != another.items[i]:
return False
return True
if __name__ == "__main__":
sample_sqlist = SequentialList()
sample_sqlist.append(11)
sample_sqlist.append(22)
sample_sqlist.append(33)
print('顺序表数据元素为:', sample_sqlist)
print('顺序表长度:', len(sample_sqlist))
print('顺序表中第0个数据元素:', sample_sqlist[0])
# 修改数据元素
sample_sqlist[1] = 2022
print('顺序表数据元素为:', sample_sqlist)
print('在顺序表位置1处添加元素2021')
sample_sqlist.insert(1, 2021)
print('添加元素后,顺序表数据元素为:', sample_sqlist)
print('删除顺序表位置2处元素')
del (sample_sqlist[2])
print('删除数据后,顺序表数据元素为:', sample_sqlist)
print('元素11的索引为{}'.format(sample_sqlist.locate(11)))
print('11在顺序表中?', 11 in sample_sqlist)
print('22在顺序表中?', 22 in sample_sqlist)
1.2 双向列表
1.2.1 特点
双向链表对于元素的添加、删除操作的开销是比较小的,只需要改变元素的前向、后向指针所指引的内容即可
双向链表的结构:
自定义节点类:包括当前节点的内容、前向节点(节点实例本身)、后向节点
属性:链表的头节点、尾节点、链表的长度
方法:
清空:构造头结点、尾节点,并使其相连,长度置为0
返回链表的长度、判断是否为空
获取索引位置的节点、更新索引节点的内容、在索引位置处添加新节点、删除节点
1.2.2 MyLinkedList(Java)
package com.ssmCombine.LeetCode;
import java.util.Iterator;
public class MyLinkedList<AnyType> implements Iterable<AnyType> {
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType d, Node<AnyType> p, Node<AnyType> n){
data = d;
prev = p;
next = n;
}
}
private int theSize;
private int modCount = 0;
private Node<AnyType> beginMarker;
private Node<AnyType> endMarker;
public MyLinkedList(){
doClear();
}
public void doClear(){
theSize = 0;
modCount++;
beginMarker = new Node<AnyType>(null, null, null);
endMarker = new Node<AnyType>(null, beginMarker, null);
beginMarker.next = endMarker;
}
public void clear(){
doClear();
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return size() == 0;
}
private void addBefore(Node<AnyType> p, AnyType x){
Node<AnyType> newNode = new Node<>(x, p.prev, p);
newNode.prev.next = newNode;
p.prev = newNode;
theSize++;
modCount++;
}
private Node<AnyType> getNode(int idx, int lower, int upper){
Node<AnyType> p;
if(idx < lower || idx > upper){
throw new IndexOutOfBoundsException();
}
if(idx < size() / 2){
p = beginMarker.next;
for (int i = 0; i < idx; i++) {
p = p.next;
}
} else {
p = endMarker;
for (int i = size(); i > idx ; i--) {
p = p.prev;
}
}
return p;
}
public void add(int idx, AnyType x){
addBefore(getNode(idx, 0, size()), x);
}
public boolean add(AnyType x){
add(size(), x);
return true;
}
private Node<AnyType> getNode(int idx){
return getNode(idx, 0, size() - 1);
}
public AnyType get(int idx){
return getNode(idx).data;
}
public AnyType set(int idx, AnyType newVal){
Node<AnyType> p =getNode(idx);
AnyType oldVal = p.data;
p.data = newVal;
return oldVal;
}
private AnyType remove(Node<AnyType> p){
p.next.prev = p.prev;
p.prev.next = p.next;
theSize--;
modCount++;
return p.data;
}
public AnyType remove(int idx){
return remove(getNode(idx));
}
@Override
public Iterator<AnyType> iterator() {
return null;
}
}
1.2.3 DoublyLinkedList(Python)
"""
Node:新的结构类型->节点
data:数据
previous:前一个节点
next:后一个节点
"""
class Node:
def __init__(self, data=None):
self.data = data
self.next = None
self.previous = None
def __str__(self):
return str(self.data)
"""
双向链表的python实现
https://www.jb51.net/article/235210.htm
"""
import CreateNode
# node = CreateNode.Node(5)
# print(node.__str__())
class DoublyLinkedList:
def __init__(self):
self.length = 0
self.head = CreateNode.Node()
def __len__(self):
return self.length
def __getitem__(self, index):
if index > self.length - 1 or index < 0:
raise IndexError("DoublyLinkedList assignment index out of range")
else:
count = -1
current = self.head
while count < index:
count += 1
current = current.next
return current.data
def __setitem__(self, index, value):
if index > self.length - 1 or index < 0:
raise IndexError("DoublyLinkedList assignment index out of range")
else:
count = -1
current = self.head
while count < index:
current = current.next
count += 1
current.data = value
def locate(self, value):
count = -1
current = self.head
while current != None and current.data != value:
count += 1
current = current.next
if current and current.data == value:
return count
else:
raise ValueError("{} is not in sequential list".format(value))
def insert(self, index, data):
count = 0
prev = self.head
if index > self.length or index < 0:
raise IndexError("DoublyLinkedList assignment index out of range")
else:
new_node = CreateNode.Node(data)
while count < index:
prev = prev.next
count += 1
new_node.previous = prev
self.length += 1
if prev.next:
new_node.next = prev.next
prev.next.previous = new_node
prev.next = new_node
else:
prev.next = new_node
def get_node(self, index):
count = -1
current = self.head
if index > self.length - 1 or index < 0:
raise IndexError("DoublyLinkedList assignment index out of range")
while count < index:
current = current.next
count += 1
return current
def __delitem__(self, index):
if index > self.length - 1 or index < 0:
raise IndexError("DoublyLinkedList assignment index out of range")
else:
current = self.get_node(index)
if current:
current.previous.next = current.next
if current.next:
current.next.previous = current.previous
self.length -= 1
del current
def __str__(self):
s = "["
current = self.head.next
count = 0
while current != None:
count += 1
s += str(current)
current = current.next
if count < self.length:
s += '<-->'
s += "]"
return s
def del_value(self, value):
current = self.head
while current:
if current.data == value:
current.previous.next = current.next
if current.next:
current.next.previous = current.previous
self.length -= 1
del current
return
else:
current = current.next
raise ValueError("The value provided is not present!")
def append(self, data):
new_node = CreateNode.Node(data)
current = self.head
while current.next:
current = current.next
current.next = new_node
new_node.previous = current
self.length += 1
if __name__ == "__main__":
dllist = DoublyLinkedList()
# 在链表末尾追加元素
dllist.append('apple')
dllist.append('banana')
dllist.append('orange')
# 在指定位置插入元素
dllist.insert(0, 'grape')
dllist.insert(4, 'lemon')
print('双向链表 sllist 为:', dllist)
print('双向链表 sllist 长度为:', len(dllist))
print('双向链表 sllist 第0个元素为:', dllist[0])
# 修改数据元素
dllist[0] = 'pear'
del (dllist[3])
print('双向修改链表 sllist 数据后:', dllist)
# 修改数据元素
dllist[0] = 'pear'
print('修改双向链表 dllist 数据后:', dllist)
dllist.insert(0, 'watermelon')
print('在位置 0 添加 watermelon 后双向链表链表 ddlist 数据:', dllist)
del (dllist[3])
print('删除位置 3 处元素后双向链表 ddlist 数据:', dllist)
dllist.append('lemon')
print('在尾部追加元素 lemon 后双向链表 ddlist 数据:', dllist)
# dllist.del_value('lemon')
# print('删除 lemon 后双向链表 dllist 数据:', dllist)
# print('watermelon 在双向链表 dllist 中的索引为:', dllist.locate('orange'))
二、堆栈
1、定义
栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫作栈的顶(top),对栈的进本操作有进栈(push)和出栈(pop),最后插入的元素可通过使用 top 在执行 pop 之前进行考查,LIFO(后进先出)
1.1 Java版
package com.ssmCombine.LeetCode;
import java.util.Arrays;
public class MyStack<T> {
// 实现栈的数组
private Object[] stacks;
// 栈的容量
private int size;
public MyStack() {
stacks = new Object[10]; // 初始容量设置为10;
}
// 判断是否为空
public Boolean isEmpty(){
return size == 0;
}
// 返回栈顶元素,但不弹出
public T peek(){
if (size > 0) {
return (T) stacks[size - 1];
} else {
return null;
}
}
// 出栈操作
public T pop(){
T t = peek();
if (size > 0) {
stacks[size - 1] = null;
size--;
}
return t;
}
// 入栈操作
public Boolean push(T t){
expandCapacity(size + 1);
stacks[size] = t;
size++;
return true;
}
/// 判断容量大小是否够用
private void expandCapacity(int n){
if(n > stacks.length){
n = n * 3 / 2 + 1;
stacks = Arrays.copyOf(stacks, n);
}
}
}
1.2 python版
"""
1、自定义堆栈
"""
class MyselfStock:
def __init__(self):
self.items = []
self.current = 0
def push(self, item):
self.items.append(item)
self.current += 1
def pop(self):
item = self.items.pop()
self.current -= 1
return item
def top(self):
return self.items[self.current - 1]
def empty(self):
return self.current == 0
if __name__ == '__main__':
s = MyselfStock()
s.push(1)
s.push(2)
s.push(3)
print(s.top())
print(s.pop())
print(s.top())
print(s.empty())
1.3 使用两个队列实现一个栈
python版
from collections import deque
class MyStack:
def __init__(self):
self.deque1 = deque()
self.deque2 = deque()
def push(self, x: int):
self.deque1.append(x)
while self.deque2:
self.deque1.append(self.deque2.popleft())
self.deque2, self.deque1 = self.deque1, self.deque2
def pop(self):
return self.deque2.popleft()
def top(self):
return self.deque2[0]
def empty(self):
return not self.deque2
if __name__ == '__main__':
st = MyStack()
st.push(5)
st.push(3)
st.push(7)
st.push(8)
st.push(1)
print(st.empty())
print(st.top())
st.pop()
print(st.pop())
三、队列
1、定义
队列也是一种表,LILO(先进先出),基本操作有入队、出队
1.1、两个栈实现一个队列
package com.ssmCombine.LeetCode;
import java.util.LinkedList;
import java.util.Stack;
/**
* 使用两个 栈 实现 一个队列
*/
public class MyQueue {
private Stack stack1;
private Stack stack2;
public MyQueue(){
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return (int) stack2.pop();
}
}