数据结构
对数组或链表进行一系列操作,结合面向对象和方法的基本知识对数据到数组在到对象的封装;来代创建一些复杂的对象来代表特殊的数据或对象。
一.动态数组
1.创建一个动态的数组;可以添加删除插入和遍历。
封装一个数组对象,在一个class文件内,没有main入口。在另外一个Test.class文件中通过创建数组对象来调用这个class文件中的变量和方法来对数组进行操作。(功能的封装必须在class非主方法外才能通过对象来调用)。
package 数据结构;
public class Test {
int [] arr= new int[5];
int index=0 ;
public void add(int n) {
if(index==arr.length) {
int temp[]=new int [arr.length+10];
/*for(int i=0;i<arr.length;i++) {
temp[i]=arr[i];
}*/
System.arraycopy(arr, 0, temp, 0, arr.length);
arr =temp;
}
arr[index++]=n;
}
//非强制便利
public void show() {
for(int i=0;i<index;i++) {
System.out.print(arr[i]+" ");
} }
//插入
public void insert(int index_,int k) {
if(index_>index&&index_<0) {
System.out.println("输入不合法");
}else {
if(index_==arr.length) {
int temp[]=new int[arr.length+10];//创建新数组
for(int i=0;i<arr.length;i++) {//将老数组中的值转移到新数组
temp[i]=arr[i];//
}
arr=temp;//将新数组的地址转换到老地址arr;
}//注意要更改新数组的范围,在移位之前
//移位
for(int i=index-1;i>=index_;i--) {
arr[i+1]=arr[i];
}
arr[index_]=k;
index++;
}
}
//update
public void update(int index_,int a) {
if(index_>=index&&index_<0) {
System.out.println("输入有误");
}else {
arr[index_]=a;
}
}
//删除
public void dlete(int index_) {
if(index_>index&&index_<0) {
System.out.println("输入有误");
}else {
for(int i= index_;i<index;i++) {
arr[i]=arr[i+1];
}
index--;
}
}
}
测试程序 Test2.class文件
package 数据结构;
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Test a=new Test();//通过创建数组对象,数组对象的封装源码必须写在class成员变量内;否则调用不出来
a.add(1);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(2);
a.add(5);
a.add(5);
a.add(5);
a.add(5);
a.add(5);
a.add(5);
a.add(5);
a.insert(3, 100);
a.show();
}
}
2.数组的扩容
package 数组.扩容;
import java.util.Arrays;
;
public class Default {
public static void main(String[] args) {
// TODO Auto-generated method stub
m1();
}
private static void m1() {
//调用System.arrayCopy()实现数组元素的复制。Ctrl{
int []data= {23,54,67,78,34,89};
//定义更大的数组
int [] newData=new int[data.length*2];
//把原来的内容赋值到新数组
//System.arraycopy(初始数组,起始位,新数组,起始位,多少个);
System.arraycopy(data,0, newData, 0, data.length);//JNI技术,在Java中调用其他语言代码
//这个方法没有方法体;及 System.arraycopy();
//让原来的数组名指向新的数组
data= newData;
System.out.println(Arrays.toString(data));
}
}
3.数组的删除
package 数组.删除;
import java.util.Arrays;
//定义一个方法,删除指定元素
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void delete(int data [],int i){
//1.定义较小的数组
int [] newDate=new int [data.length-1];
//2.把0,1复制到新的数组中,在i+1开始到 data.length
for(int t=0;t<i ;t++) {
newDate[t]=data[t];
}
for(int t=i+1;t<data.length;t++) {
newDate[t-1]=data[t];
}
//4.让原来的数组指向新的数组
data= newDate;
//打印data
System.out.println(Arrays.toString(data));
}
}
二.动态链表
1.创建一个单项链表,可以插 删 改查等动态操作。与动态数组相比,插删改效率更高。在链表中没有下标的概念
## 创建一个节点类
```c
package 数据结构;
public class Node {
int value;
Node next;//Node类型,代表下一个节点的是next,
//可以通过next.value 和next.next来表示这个节点的值和下一个节点的名称
}
封装链表
package 数据结构;
public class MyLinked {
Node n1;//存的一个 链表的头 Node是自己创建的类
int size=0;//链表元素的个数
public void add(int a) {
if(size==0) {
Node node=new Node();
node.value=a;
node.next=null;
n1 =node;//n1是第一个节点
size++;
}else {
Node node=new Node();
node.value=a;
node.next=null;//创建最后这个节点为node
Node tail=n1;//认为要插入的节点上一个节点定为tail,并默认时n1;并且遍历直到找到node.tail
while (tail.next!=null) {
tail=tail.next;
}
tail.next=node;//将要加入的新节点node(是通过新定义的类Node创建的)插入到tail后面
}
}
//链表的遍历
public void foreach() {
Node tail=n1;
while(tail.next!=null) {//当链表内下个值不为null,说明是中间元素。
System.out.println(tail.value+" ");
tail=tail.next;//在循环内说明tail不是最后的元素,将下一个节点传给tail直到跳出循环
}//跳出循环后,输出的tail就是最后的元素,tail.next=null.遍历已经全部遍历
}
//链表插入不需要考虑移位
public void insert(int v,int a) {//v是链表中要插入值之前的那个值
node tail=n1;//设置为n1,表示从n1的位置开始遍历,直到不满足循环的条件
while(tail.value!=v) {//循环遍历直到找到v这个结果的节点
tail=tail.next;
}
//创建这个要插入的节点
Node node=new Node();
node.value=a;
node.next=tail.next;
tail.next=node;//把新创建的节点添加到tail后,
size++;
}
public void delete(int v) {
Node tail=n1;
while(tail.next.value!=v) {//判断当前节点下一个节点是否被删除,跳出循环被删要
tail=tail.next;
}
tail.next=tail.next.next;//被删除的节点直接被在下一个节点取代掉
size--;
}
public void update(int v,int v1) {
Node tail=n1;
while(tail.value!=v) {//判断当前节点下一个节点是否被删除,跳出循环被删要
tail=tail.next;
}
tail.value=v1;//被删除的节点直接被在下一个节点取代掉
}
public int size() {
return size;
}
}
## 测试类
```c
```java
```c
package 数据结构;
public class lion {
public static void main(String[] args) {
MyLinked a =new MyLinked();
a.add(5);
a.add(6);
a.add(1);
a.add(6);
a.add(7);
a.add(3);
a.add(9);
a.add(6);
a.add(7);
a.foreach();
}
}
三.队列
1.队列常用于解决高并发、优先级等问题;需要自己设置相应的算法来解决。 实现了动态队列
package 队列;
public class Default {
int[] arr =new int[10];
int size=0;
//追加元素 入队列
public void push(int a) {//常规操作,和栈差不多
if(size==arr.length) {
int[] temp=new int[arr.length+arr.length>>1];
System.arraycopy(arr, 0, temp, 0, arr.length);
arr=temp;
}
arr[size++]=a;//size要先赋值,在增一。表示的是刚加入的元素
}
//出队列,删除
public int pop() {//需要向前移位
int temp=arr[0];//移位后头头元素会发生变化,故先赋值给temp
for(int i= 0;i<size;i++) {
arr[i]=arr[i+1];//移位
}
size--;
return temp;
}
//查看头元素
public int peek(){
return arr[0];
}
//循环
public void foreach() {
for(int i=0;i<size;i++) {
System.out.println(arr[i]+" ");
}
}
//获取大小
public int size() {
return size;
}
}
//高并发问题 同一时刻很多人访问服务器
/*1.用队列
*
* 2.负载均衡
*
*
*
*
* */
//发邮件
2.插入排序法实现优先级
按大小来排队列,大的数靠前排;默认大的优先级高
package 队列.优先级;
//插入排序法,越大越靠前
//或者哈希算法来
public class Default {
int[] arr =new int[10];
int size=0;
//追加元素 入队列
public void push(int a) {//常规操作,和栈差不多
if(size==arr.length) {
int[] temp=new int[arr.length+arr.length>>1];
System.arraycopy(arr, 0, temp, 0, arr.length);
arr=temp;
}
//将a插入合适的位置,用插入排序9631 5该擦到6后面
int index =0;//认为在第0个位置是合适的
boolean flag=false;
for(int i=0;i<size;i++) {//可能全部走完一圈也没
if(a>arr[i]) {
index=i;
flag=true;//表面未遍历完就找到了位置
break;
}
}
if(flag) {//表明进去了if语句
//移位
for(int k=size-1;k>=index;k--){//向后移,从后往前循环
arr[k+1]=arr[k];
}
arr[index]=a;
size++;
}else {
index=size;
arr[index]=a;
size++;
}
}
//出队列,删除
public int pop() {//需要向前移位
int temp=arr[0];//移位后头头元素会发生变化,故先赋值给temp
for(int i= 0;i<size;i++) {
arr[i]=arr[i+1];//移位
}
size--;
return temp;
}
//查看头元素
public int peek(){
return arr[0];
}
//循环
public void foreach() {
for(int i=0;i<size;i++) {
System.out.println(arr[i]+" ");
}
}
//获取大小
public int size() {
return size;
}
}
测试类Test
package 队列.优先级;
public class Test {
public static void main(String[] args) {
Default a=new Default();
a.push(5);
a.push(1);
a.push(9);
a.push(8);
a.push(6);
a.push(4);
a.push(3);
a.push(7);
a.foreach();
}
}
3.循环队列
package 队列.循环;
//一个圈,首尾相连。不考虑优先级
/*加入是放在队尾,只有查看大小不用该
*
* */
public class Default {
int[] arr =new int[10];
int size=0;
/*int first=0;//代表有一个元素
int tail=0;*/
int first_index=-1;
int tail_index=-1;
//追加元素 入队列
public void push(int a) {//常规操作,和栈差不多
//为空,插入一个首尾都
if(first_index==-1&&tail_index==-1) {
arr[++tail_index]=a;//
first_index++;
}else {
arr[++tail_index]=a;//if else里都有++tail_index;可以拿出来去掉else在if后表示
}
size++;
}
//出队列
public int pop() {//需要向前移位
//就一个元素,取完后尾和头都变-1
//多个元素,只改头指向下个
int temp;
if(size==1) {
temp=arr[first_index];
first_index=-1;
tail_index=-1;
}else {
temp=arr[first_index];//将头元素指向下一个元素
if(first_index==arr.length) {
first_index=0;//归零,因为循环是一个圈0,1,2,3,4,5,6,7,8,9
}
}
size--;
return temp;//查看抛出的元素
}
//查看头元素
public int peek(){
return arr[first_index];//直接指向头文件指向的位置
}
//循环 改功能未实现
/*public void foreach() {
for(int i=0;i<size;i++) {
int index=first_index;
System.out.println(index);
if(first_index==tail_index) {
System.out.println(index++);
break;
}else {
System.out.println(index++);
if(first_index==)
}
}
}*/
//获取大小
public int size() {
return size;
}
}
树
1.搜索树
节点左右孩子所存储的值呈现左<根<右;称搜索树 可以直接去掉一半的值进行比较,效率高
2.平衡树
高度差<=1称平衡树
改为平衡树: 单旋和双旋(单旋:提起较深一段的父类 双选:提起父类和跟类中间;提起的那段的尾端放在最左面的下面)
3.树的代码实现