源代码: Java数据结构与基本算法
1. 数据结构简介
1.1 定义
数据结构就是研究数据的逻辑结构,存储结构和运算方法的统筹感念。数据的逻辑结构包括:线性结构,树形结构,图形结构。线性结构指的是一对一的关系,树形结构存在一对多的关系,图形结构存在多对多的关系,存在一对多和多对多关系的又称为非线性结构
1.2 存储方式
数据结构的存储结构:顺序存储(ArrayList),链式存储(LinkedList),索引存储(B-Tree和自定义索引),散列存储(hasCode)
2. 数据结构 — 线性表
线性表是一种线性数据结构,元素存在"一对一的关系",线性表的每个数据元素的类型都是相同的
代表性的有:一维数组和线性链表
2.1 数组
2.1.1 基本类型数组
例如:向一维数组做,插入,更新,替换,删除操作时:
// 声明一个数组
int[] scores = {1, 2, 3, 4, 5, 6};
// 1. 在数据尾部位置插入一个数字
scores = add(scores, 7);
public static int[] add(int[] array, int score) {
int[] tempArray = new int[array.length + 1];
for (int i = 0; i < array.length; i++) {
tempArray[i] = array[i];
}
tempArray[array.length] = score;
return tempArray;
}
// 2. 向一维数组任意位置(指定位置)修改一个数据,真实位置=要求位置-1
scores = update(scores, 7, 2);
public static int[] update(int[] arrary, int score, int index) {
arrary[index] = score;
return arrary;
}
// 3. 替换一个数字到指定位置
scores = insert(scores, 7, 2);//将75插入到索引为2的位置
public static int[] insert(int[] array, int score, int index) {
int[] tempArray = new int[array.length + 1];
for (int i = 0; i < array.length; i++) {
if (i < index) {
tempArray[i] = array[i];
} else {
tempArray[i + 1] = array[i];
}
}
tempArray[index] = score;
return tempArray;
}
// 4. 删除指定位置的数字
scores = delete(scores, 3);
public static int[] delete(int[] array, int index) {
int[] tempArray = new int[array.length - 1];
for (int i = 0; i < array.length; i++) {
if (i <= index) {
tempArray[i] = array[i];
} else {
tempArray[i - 1] = array[i];
}
}
return tempArray;
}
2.1.2 封装类型ArrayList数组
//声明初始接口方法
public interface List {
public void add(Object element);//添加元素
public Object get(int index);//获得元素
public Object set(int index,Object element);//修改元素
public Object remove(int index);//删除元素
public int size();//集合大小
}
//实现声明接口的数组
public class ArrayList implements List {
private int initCapacit = 20;//初始数组大小
private int size;//元素个数
private Object[] elementData;//数据数组对象
public ArrayList() {
elementData = new Object[initCapacit];
}
public ArrayList(int initCapacit) {
elementData = new Object[initCapacit];
this.initCapacit = initCapacit;
}
//添加元素
@Override
public void add(Object element) {
if (size < initCapacit) {
elementData[size] = element;
size++;
} else {
elementData = expandArray(elementData);
elementData[size] = element;
size++;
}
}
//扩充List对象数组大小
public Object[] expandArray(Object[] elementData) {
Object[] tempArray = new Object[elementData.length * 2];//每次扩充为原来的2倍大小
for (int i = 0; i < elementData.length; i++) {
tempArray[i] = elementData[i];
}
return tempArray;
}
//获得元素
@Override
public Object get(int index) {
return elementData[index];
}
//集合大小
@Override
public int size() {
return size;
}
//删除元素
@Override
public Object remove(int index) {
Object removeObj = elementData[index];
//删除元素后面的元素前移
for (int i = index; i < size; i++) {
elementData[i] = elementData[i + 1];
}
size--;
return removeObj;
}
//修改元素
@Override
public Object set(int index, Object element) {
elementData[index] = element;
return element;
}
2.1.3 ArrayList数组迭代器
public interface List {
public Iterator iterator();//获取迭代器;;
}
public interface Iterator {
public boolean hasNext();//是否有下一个元素
public Object next();//获得下一个元素
}
//是否有下一个元素
@Override
public boolean hasNext() {
return index < list.size();
}
//获得下一个元素
@Override
public Object next() {
Object element = null;
if (index < list.size()) {
element = list.get(index);
index++;
}
return element;
}
//迭代打印集合元素
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
2.2 链表
2.2.1 单链表
//单链表的结构,Node的自引用,next代表指针变量指向下一个节点
public class Node {
private String data;//节点数据
private Node next;//下一个节点
public Node(String data, Node next) {
this.data = data;
this.next = next;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
2.2.2 单循环链表
// 核心在于打印两次,头开始到尾,再从尾到头循环打印
public static void print(Node node) {
Node p = node;
Node startNode = node;
int circleCount = 0;//循环打印次数
while (circleCount < 2) {
//从头开始到尾,再从尾到头循环打印
String data = p.getData();
System.out.print(data + "→");
p = p.getNext();
if (p.getNext() == startNode) {
circleCount++;
}
}
String data = p.getData();
System.out.print(data + "\n\n");
}
2.2.3 双链表
// 双链表,prev和next两个指针变量 prev-data-next
class Node {
private String data;//结点数据
private Node prev;//上一个结点
private Node next;//下一个结点
public Node(String data, Node prev, Node next) {
this.data = data;
this.prev = prev;
this.next = next;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
2.2.4 双向循环链表
nt circleCount = 0;//循环打印次数
while (circleCount < 2) {
//从头开始直到尾结束,再从尾到头循环打印
String data = p.getData();
System.out.print(data + "->");
p = p.getNext();
if (p.getNext()==startNode){
circleCount++;
}
}
2.2.5 LinkedList实现
public interface List {
public void add(Object element);//添加元素
public Object get(int index);//获得元素
public Object set(int index,Object element);//修改元素
public Object remove(int index);//删除元素
public int size();//集合大小
}
//节点内部类,双向
class Node {
private Object data;//节点数据
private Node prev;//上一个节点
private Node next;//下一个节点
public Node(Object data,Node prev,Node next){
this.data=data;
this.prev=prev;
this.next=next;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public class LinkedList implements List {
private Node head;//定义头节点
private Node tail;//定义尾节点
private int size;//元素个数
public LinkedList(){
}
//表尾插入数据,没有指定位置
@Override
public void add(Object element) {
if (head==null){
head=new Node(element,null,null);
tail=head;
}
else {
Node newNode=new Node(element,null,null);
tail.setNext(newNode);
newNode.setPrev(tail);
tail=newNode;
}
size++;
}
@Override
public Object get(int index) {
Node p=head;
int i=0;
while (p.getNext()!=null && i<index)
{
p=p.getNext();
i++;
}
return p.getData();
}
@Override
public int size() {
return size;
}
@Override
public Object set(int index, Object element) {
Node p=head;
int i=0;
while (p.getNext()!=null && i<index){
p=p.getNext();
i++;
}
p.setData(element);
return element;
}
@Override
public Object remove(int index) {
Node p=head;
int i=0;
while (p.getNext()!=null && i<index){
p=p.getNext();
i++;
}
Node temp=p;//保存要删除的节点
p.getPrev().setNext(p.getNext());
p.getNext().setPrev(p.getPrev());
temp.setNext(null);
temp.setPrev(null);
size--;
return temp.getData();
}
}
2.2.6 LinkedList迭代器
public interface List {
public Iterator iterator();//获取迭代器;;
}
public interface Iterator {
public boolean hasNext();//是否有下一个元素
public Object next();//获得下一个元素
}
@Override
public boolean hasNext() {
return currentNode!=null;
}
@Override
public Object next() {
Object element=null;
element=currentNode.getData();
currentNode=currentNode.getNext();
return element;
}
//迭代打印元素
Iterator iterator=list.iterator();
while (iterator.hasNext()){
Object obj=iterator.next();
System.out.println(obj);
}
2.3 栈
栈是限制在表尾进行插入和删除的线性表,特性是先进后出,主要应用在铁路和存放桶
2.4 队列
队列(Single Queue)是限制在表的两端进行操作的线性表,主要特点是"先进先出",队首部允许删除,队尾允许插入
2.5 串
串是零个或多个任意字符组成的有限队列,串也分顺序存储和链式存储,Java中有基本字符类型Char和封装字符串类型String类
2.6 多维数组
2.6.1 二维数组
2.7 广义表
3. 数据结构 之 非线性表
3.1 树
3.1.1 二叉树
3.1.2 红黑树
3.2 图
3.2.1 无向图
3.2.1.1 广度优先搜索
3.2.1.1 深度优先搜索
3.2.2 有向图
3.2.2.1 广度优先搜索
3.2.2.1 深度优先搜索
3.3 散列表
3.3.1 哈希
3.3.2 自定义存储
3.4 堆
3.4.1 大顶堆
3.4.2 小顶堆
4. 查找
查找分为静态查找和动态查找(对查找表进行插入元素或删除元素的操作)
静态查找表包含顺序查找,分块查找和二分折半查找(效率较高)