双向链表的搜索速度方差
/*
关于双链表的搜索给定元素操作的说法正确的是
正确答案: B
从两个方向搜索双链表,比从一个方向搜索双链表的速度慢
从两个方向搜索双链表,比从一个方向搜索双链表的方差要小
从两个方向搜索双链表,比从一个方向搜索双链表速度要快
以上说法都不正确
如果链表数据是无序的,则搜索速度一样快,
如果是有序的,则又向搜索比单向搜索更快
因此综合起来,搜索速度的方差,双向搜索时更小
*/
适合存放数据元素的结构
/*
某一系统功能,需要一次性加载N(N在1000左右)个随机数
后续只对该集合进行遍历。最宜采用哪种结构存放?
正确答案: C
Hash表
二叉树
链表
图
随机数,未经排序,二叉树不适合,二叉树自动排序,TreeSet可排序集合;
需要遍历,hash表不适合;
不强调数据之间的关系,图不适合;
随机数数据类型不一致,数组不适合。
综上所述,链表最适合。
数组:连续存储,遍历快且方便,长度固定,缺点移除和添加 需要迁移n个数据或者后移n个数据
链表:离散存储,添加删除方便,空间和时间消耗大,双向链表比单向的更灵活,但是空间耗费也更大
Hash表:数据离散存储,利用hash算法决定存储位置,遍历麻烦。以java的HashMap为例
二叉树:一般的查找遍历,有深度优先和广度优先,遍历分前序、中序、后序遍历,效率都差不多
但是如果数据经过排序,二叉树效率还是不错。
*/
有无符号位运算
public static void main(String[] args) {
/*
>> 表示带符号右移,如果为负数,符号位补1
>>> 表示无符号右移,忽略符号位
*/
System.out.println(20 >>> 2); // 5
System.out.println(-20 >> 2); // -5
System.out.println(-20 >>> 2); // 1073741819
}
类变量和局部变量
/*
下列程序的输出结果是
*/
class Test {
public static int a = 1;
public static void main(String[] args) {
int a = 10;
a++; // 类变量+1
Test.a++; // 局部变量+1
Test t=new Test();
System.out.println("a=" + a + " t.a=" + t.a);
// a = 11 t.a = 2
/*
值为1的a属于类变量也叫作成员变量,
值为10的a是局部变量
首先a++时就近原则,用局部变量10来加
Text.a直接用类名调用成员变量的情况
只能是static修饰的成员变量1来加,然后又实例化了对象,
在输出中第一个a=用就近原则输出11,
第二个t.a实际会找t的类型
也就相当于Test.a
*/
}
}
(important)依赖注入和控制反转
/*
Short answer question: How to implement dependency injection in the simplest way,
and how does dependency injection achieve decoupling?
简答题:如何用最简单的方式实现依赖注入,依赖注入是如何实现解耦的
举一个通俗易懂的例子
John有一部手机,最爱用手机做的事情就是
逛优快云,逛简书,购物
于是有了两个类
public class John extend Person
public class IPhoneX extend Phone
John借助IPhoneX做这3件事情
new iPhone6().read(String string)
new iPhone6().visit(String string)
new iPhone6().shop(String string)
然后
John的手机坏了,换了一部新手机,叫做IPhone6
John需要重新适应这部手机的各项功能
也就是把John类里面的所有的IPhoneX都改为Iphone6
这个过程很漫长,也很累
又有一次John的手机丢了
John不想再经历这样改造自己的过程
这时,John和手机已经过度耦合了
这时,程序员使用了控制反转
手段是依赖注入
总结:
如果A类功能的实现依赖于B
那么称为B类是类A的依赖
如果在A的内部去实例化B
那么两者之间会出现较高的耦合
一旦B类出现了问题
A类页需要改造
想象一下,这只是2个类
如果10个类都是这样的情况
那么将牵一发而动全身
程序将难以维护
要解决这个问题
就需要A类把控制权交给第3方
这就叫做控制反转
然后通过构造函数,属性和工厂模式来注入给A类
下面我写了一个实例
*/
// 解耦前
class Main {
public static void main(String[] args) {
/*
根据这一段代码
Main类与Chinese和American类产生了强耦合
也就是如果Chinese和American类的方法修改时
这里也需要修改
*/
Chinese chinese = new Chinese();
chinese.sayHelloWorld("张三");
American american = new American();
american.sayHelloWorld("Jack");
}
}
interface Human {
public void sayHelloWorld(String name);
}
class Chinese implements Human {
public void sayHelloWorld(String name) {
String helloWorld = "你好," + name;
System.out.println(helloWorld);
}
}
class American implements Human {
public void sayHelloWorld(String name) {
String helloWorld = "Hello," + name;
System.out.println(helloWorld);
}
}
// 解耦后
class Main {
public static void main(String[] args) {
/*
工厂模式在一定程度上降低耦合度
当Chinese类和American类里面的方法修改时
Main类只需要修改方法和参数
仅仅与接口Human耦合
*/
HumanFactory humanFactory = new HumanFactory();
Human human1 = humanFactory.getHuman("chinese");
human1.sayHelloWorld("张三");
Human human2 = humanFactory.getHuman("american");
human2.sayHelloWorld("Jack");
}
}
interface Human {
public void sayHelloWorld(String name);
}
/*
工厂类
*/
class HumanFactory {
public Human getHuman(String type) {
if ("chinese".equals(type)) {
return new Chinese();
} else {
return new American();
}
}
}
class Chinese implements Human {
public void sayHelloWorld(String name) {
String helloWorld = "你好," + name;
System.out.println(helloWorld);
}
}
class American implements Human {
public void sayHelloWorld(String name) {
String helloWorld = "Hello," + name;
System.out.println(helloWorld);
}
}
Integer自动装箱
/*
下列程序输出结果是
*/
Integer a1 = 1;
Integer b1 = 1;
Integer c1 = 500;
Integer d1 = 500;
System.out.print(a1 == b1); // true
System.out.print(c1 == d1); // false
/*
Integer类型在-128-->127范围之间是被缓存了的,也就是每个对象的内存地址是相同的
赋值就直接从缓存中取,不会有新的对象产生,而大于这个范围
将会重新创建一个Integer对象,也就是new一个对象出来,当然地址就不同了
Integer a = 1;是自动装箱会调用Interger.valueOf(int)方法;该方法注释如下:
This method will always *** values in the range -128 to 127 inclusive,
and may *** other values outside of this range.
也就是说IntegerCache类缓存了-128到127的Integer实例,在这个区间内调用valueOf不会创建新的实例
*/
构造方法赋值
class TestDemo{
private int count;
public static void main(String[] args) {
TestDemo test=new TestDemo(88);
System.out.println(test.count); // 88
}
TestDemo(int a) {
/*
创建新对象时,调用构造方法
将a值赋值给count变量
成员变量在构造方法里面可以进行赋值操作
*/
count=a;
}
}
代码块执行顺序
class HelloA {
public HelloA() {
System.out.println("A的构造函数");
}
{
System.out.println("A的构造代码块");
}
static {
System.out.println("A的静态代码块");
}
public static void main(String[] args) {
HelloA a = new HelloA();
}
}
/*
加载顺序:
1.父类静态代码块
2.子类静态代码块
3.父类构造代码块
4.父类构造函数
5.子类构造代码块
6.子类构造方法
总结:先静态后非静态,先父类后子类
静态代码块 > 构造代码块 > 构造函数
*/
Java数据结构与算法:双向链表搜索速度探讨
本文主要探讨了Java中双向链表的搜索速度方差,分析了适合存放数据元素的结构,讲解了有无符号位运算在数据处理中的应用,并深入讨论了类变量和局部变量的区别。此外,还重点介绍了依赖注入和控制反转的概念,以及Integer自动装箱、构造方法赋值和代码块执行顺序等核心概念。
505

被折叠的 条评论
为什么被折叠?



