java - 数据结构 - 基础数据结构
整理所学,期待批评指教
基础概念
-
数据
- 描述客观事物的数值、字符以及能输入到计算机中且能被处理的各种符号集合
-
数据元素
- 组成数据的基本单位,数据集合的个体,计算机中通常作为一个整体进行考虑
-
数据对象
- 性质相同的数据元素的集合,数据的一个子集
-
数据结构
-
相互之间存在一种或多种特定关系的数据元素的集合
-
是一个二元组:
D —>数据有限集
R —>D上关系的有限集
- Data_Stracture = (D, R)
-
-
数据类型
- 性质相同的值集合以及定义在这个值集合上的一组操作的总称。
-
数据抽象与抽象数据类型
- 抽象数据类型(Abstract Data Type)ADT
- 含义:数据模型及定义在数据模型上的操作
- 特征:使用与实现分离,实现信息封装及隐蔽
- 抽象数据类型实现
- 1.面向过程设计
- 逻辑架构—>选定存储结构,操作要求—>设计子程序或子函数
- 2.“包”,“模型”设计方法
- 可单独编译,同时提供了外部使用的方便
- 3.面向对象程序设计(Object Oriented Programming,OOP)
- 着眼于应用问题涉及的对象,包括对象,对象属性和要求
- 1.面向过程设计
- 抽象数据类型(Abstract Data Type)ADT
1.数据结构内容
1.1 数据的逻辑结构
数据逻辑间关系的描述
- 依据数据间不同关系划分
- 集合结构:结构中数据元素除同属于一个集合外无任何关系
- 线性结构:结构中数据元素存在着一对一的线性关系
- 树型结构:结构中的数据元素之间存在着一对多的层次关系
- 图状结构:结构中的数据元素之间存在着多对多的任意关系
- 依据数据元素间关系的不同特性
- 线性结构:
- 线性表,栈,队列,字符串,数组和广义表
- 非线性结构:
- 树和图
- 线性结构:
1.2 数据的存储结构
- 数据元素在计算机中的表示方式
- 顺序映像—>顺序存储
- 非顺序映像—>链式存储
1.3 数据的运算
Niklaus Wirth提出的著名公式:数据结构 + 算法 = 程序
- 算法特征
- 有穷性:任意一组合法输入值,又穷步骤后一定能结束
- 确定性:每一步是确切定义的,算法的执行者或者阅者都能明确其含义以及如何执行,并且在任何条件下,算法只有一条执行路径
- 可行性:算法中所有操作必须足够基本,都可以通过已实现的基本操作运算有限次实现
- 有输入:算法应该有0个或多个输入
- 有输出:算法应该有1个或多个输出
- 算法评定标准
- 正确性
- 可读性
- 健壮性
- 高效率与低存储量需求
2.线性表
2.1 线性表基本概念
- 特点:
- 同一性
- 有穷性
- 有序性
2.2 线性表的实现
存储方式:链式存储,顺序存储
2.2.1 基本概念
-
逻辑上相邻的物理存储上也是相邻的
-
计算函数:
-
第一个元素存放地址LOC(a1),每个元素占用d个字节
LOC(ai) = LOC(a1) + d x (i-1) 1<= i <= n
-
-
优势存取随机
2.2.2 实现
-
规定其接口
package algorithm.base.linearList; /** * @ClassNameMyList * @Description * @Author ANGLE0 * @Date 2019/12/21 14:44 * @Version V1.0 **/ public interface MyList { void clear(); boolean isEmpty(); int length(); Object get(int i) throws Exception; void insert(int i, Object x) throws Exception; void remove(int i) throws Exception; int indexOf(Object x); void display(); }
2.2.2.1顺序存储实现
package algorithm.base.linearList;
/**
* @ClassNameArrayList
* @Description
* @Author ANGLE0
* @Date 2019/12/21 13:03
* @Version V1.0
**/
public class MyArrayList implements MyList{
private Object[] elements;
private int length;
public MyArrayList(int length) {
this.elements = new Object[length];
this.length = 0;
}
/**
* @Desc: [清空顺序表]
* @param : void
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 14:51
* @version : v1.0
*/
public void clear() {
this.length = 0;
}
/**
* @Desc: [是否为空]
* @param : void
* @return : boolean
* @author : ANGLE0
* @createTime : 2019/12/21 14:51
* @version : v1.0
*/
public boolean isEmpty() {
return this.length == 0;
}
/**
* @Desc: [返回当前顺序表的长度]
* @param : void
* @return : int
* @author : ANGLE0
* @createTime : 2019/12/21 14:50
* @version : v1.0
*/
public int length() {
return this.length;
}
/**
* @Desc: [返回指定位置数据值]
* @param : int
* @return : Object
* @author : ANGLE0
* @createTime : 2019/12/21 14:52
* @version : v1.0
*/
public Object get(int i) throws Exception {
if (i < 0 && i > this.length)
throw new NullPointerException("顺序表中不存在"+i+"位置");
return elements[i];
}
/**
* @Desc: [在指定位置插入值,前置插入]
* eg:[ 1, 2, 3, 4, 5] ---> insert(2, 0) ---> [1, 0, 2, 3, 4, 5]
* @param : int , Object
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 14:59
* @version : v1.0
*/
public void insert(int i, Object in) throws Exception {
//边界判定
if (i == elements.length)
throw new Exception("当前表已满,插入失败");
if (i < 0 || i > elements.length)
throw new NullPointerException("插入"+i+"位置不合适,数据"+in.toString()+"插入失败");
//为即将插入的值调整空间
for (int j = this.length; j > i; j--){
elements[j] = elements[j-1];
}
//赋值修改顺序表元素长度记录
elements[i] = in;
this.length++;
}
/**
* @Desc: [移除当前位置所指向的元素]
* @param : int
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 15:17
* @version : v1.0
*/
public void remove(int i) throws Exception {
//边界判定
if (this.length == 0)
throw new NullPointerException("顺序表已空");
if (i > this.length || i < 0)
throw new NullPointerException("要移除的"+i+"位置不存在");
//元素左移,覆盖原有值,实现删除
for (int j = i; j < this.length-1; j++) {
elements[j] = elements[j+1];
}
//修改顺序表长度记录
this.length--;
}
/**
* @Desc: [查找指定值在顺序表中的位置]
* @param : Object
* @return : int
* @author : ANGLE0
* @createTime : 2019/12/21 15:23
* @version : v1.0
*/
public int indexOf(Object x) {
int index = 0;//记录当前扫描位置
while (index < this.length && !elements[index].equals(x)){
index++;
}
return index < this.length ? index : -1;
}
/**
* @Desc: [打印顺序表值]
* @param : void
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 15:23
* @version : v1.0
*/
public void display() {
System.out.print("[");
for (int i = 0; i < this.length-1; i++) {
System.out.print(" "+ elements[i] + ",");
}
System.out.print(" "+ elements[this.length-1] + "]\n");
}
}
测试
public static void main(String[] args) throws Exception {
MyArrayList L = new MyArrayList(10);
for (int i = 0; i < 8; i++)
L.insert(i, i);
System.out.println("删除索引为1的元素");
L.remove(1);
L.display();
System.out.println("索引为3处插入元素");
L.insert(3, 5);
L.display();
System.out.println("获取索引为1的元素值");
System.out.println(L.get(1));
}
/* 测试结果为*/
删除索引为1的元素
[ 0, 2, 3, 4, 5, 6, 7]
索引为3处插入元素
[ 0, 2, 3, 5, 4, 5, 6, 7]
获取索引为1的元素值
2
2.2.2.2 链式存储实现
package algorithm.base.linearList.link;
import algorithm.base.linearList.MyList;
import javax.management.loading.MLet;
/**
* @ClassNameMyLinkedList
* @Description
* @Author ANGLE0
* @Date 2019/12/21 17:14
* @Version V1.0
**/
public class MyLinkedList<E> implements MyList {
private E data;
private MyLinkedList next;
public MyLinkedList() {
}
/**
* @Desc: [初始化链表]
* @param : MyLinkedList
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 17:22
* @version : v1.0
*/
public MyLinkedList(Object x) {
this.data = (E)x;
this.next = null;
}
/**
* @Desc: [清空链表]
* @param : void
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 17:22
* @version : v1.0
*/
public void clear() {
this.next = null;
}
/**
* @Desc: [链表是否为空]
* @param : void
* @return : boolean
* @author : ANGLE0
* @createTime : 2019/12/21 17:23
* @version : v1.0
*/
public boolean isEmpty() {
return this.data == null && this.next == null;
}
/**
* @Desc: [链表长度]
* @param : void
* @return : int
* @author : ANGLE0
* @createTime : 2019/12/21 17:23
* @version : v1.0
*/
public int length() {
int count = 0;
MyLinkedList linkedList = this;
if (linkedList != null){
count++;
linkedList = linkedList.next;
}
return count;
}
/**
* @Desc: [获取索引为i的值]
* @param : void
* @return : Object
* @author : ANGLE0
* @createTime : 2019/12/21 17:26
* @version : v1.0
*/
public E get(int i) throws Exception {
int count = 0;
MyLinkedList linkedList = this;
while (count < i){
linkedList = linkedList.next;
}
return (E)linkedList.data;
}
/**
* @Desc: [插入节点,前置插入]
* @param : int, Object
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 18:35
* @version : v1.0
*/
public void insert(int i, Object x) throws Exception {
MyLinkedList myLinkedList = this.NodePreI(i);
//创建新元素并嵌入链表中
MyLinkedList newNode = new MyLinkedList(x);
newNode.next = myLinkedList.next;
myLinkedList.next = newNode;
}
/**
* @Desc: [移除第i个节点]
* @param : int
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 18:39
* @version : v1.0
*/
public void remove(int i) throws Exception {
MyLinkedList myLinkedList = NodePreI(i);
myLinkedList.next = myLinkedList.next.next;
}
/**
* @Desc: [返回第i-1个节点]
* @param : int
* @return : MyLinkedList
* @author : ANGLE0
* @createTime : 2019/12/21 18:54
* @version : v1.0
*/
private MyLinkedList NodePreI(int i) {
MyLinkedList myLinkedList = this;
if (this == null)
throw new NullPointerException("链表为空,索引"+i+"位置无效");
if (i < 0){
throw new NullPointerException("索引位置越界,索引"+i+"无效");
}
//遍历到第i个节点前一个节点
for (int j = 0; j < i-1; j++) {
myLinkedList = myLinkedList.next;
}
return myLinkedList;
}
/**
* @Desc: [查找出第一个值为x的索引位置]
* @param : Object
* @return : int -1代表查询无结果
* @author : ANGLE0
* @createTime : 2019/12/21 18:40
* @version : v1.0
*/
public int indexOf(Object x) {
MyLinkedList myLinkedList = this;
if (this == null)
throw new NullPointerException("链表为空,查找失败");
MyLinkedList myLinkedList1 = this;
int count = 0;
while (myLinkedList1.next != null && myLinkedList1.data.equals(x)) {
myLinkedList1 = myLinkedList1.next;
count++;
}
return count > this.length() ? -1 : count;
}
/**
* @Desc: [打印当前链表的所有值]
* @param : void
* @return : void
* @author : ANGLE0
* @createTime : 2019/12/21 18:44
* @version : v1.0
*/
public void display() {
MyLinkedList myLinkedList = this;
while (myLinkedList.next != null){
System.out.print(myLinkedList.data + "-->");
myLinkedList = myLinkedList.next;
}
System.out.print("\b\b\b \n");
}
}
测试
public static void main(String[] args) throws Exception {
MyLinkedList myLinkedList = new MyLinkedList(0);
for (int i = 0; i < 10; i++) {
myLinkedList.insert(i, i);
}
System.out.println("建立链表如下:");
myLinkedList.display();
System.out.println("索引为1处插入数值9");
myLinkedList.insert(1, 9);
myLinkedList.display();
System.out.println("移除索引为3的节点");
myLinkedList.remove(3);
myLinkedList.display();
System.out.println("清除链表");
myLinkedList.clear();
myLinkedList.display();
}
/* 测试结果 */
建立链表如下:
0-->1-->2-->3-->4-->5-->6-->7-->8-->9
索引为1处插入数值9
0-->9-->1-->2-->3-->4-->5-->6-->7-->8-->9
移除索引为3的节点
0-->9-->1-->3-->4-->5-->6-->7-->8-->9
清除链表
来源:CSDN
作者:ANG-X
链接:https://blog.csdn.net/qq_42070179/article/details/103647519