什么是数据结构:

数据结构是计算机存储、组织数据的方式。

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。

    

常见的数据结构

数组,栈,链表,哈希表,队列,堆,图,树

       Java中集合框架其实就是数据结构的实现的封装,今天是我们自己从头来模拟和实现数据结构.

      不同的数据结构的操作性能是不同的:(有的查询性能很快,有的插入速度很快,有的是插入头和尾速度很快,有的做等值判断很快,有的做范围查找很快,有的允许元素重复,有的不允许重复等等),在开发中如何选择,要根据具体的需求来选择.

 

       最简单的数据结构就是数组.

什么是集合框架:

集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法(底层都对应着某一种数据结构的算法)。

--------------------------------------------------------------------------------------------------------------------------------

为什么需要集合框架(把集合框架的类和接口都存放在java.util包中):

    1):提供功能的复用(java.util包).

    2):让程序猿专注于业务开发,而不是数据结构和算法.

--------------------------------------------------------------------------------------------------------------------------------

常用的框架接口规范:

  集合中存储的对象,称之为集合元素.

常用的集合类:

   Set(集):集合中的对象不按特定方式排序,不允许元素重复.

   List(列表):集合中的对象按照索引位置排序,允许元素重复.

   Map(映射):集合中每一个元素都包含一对key和value对象.不允许key对象重复,值对象可以重复.

Java基础(三)

 

ArrayList操作的性能分析

发现:基于数组的结构做查询是和修改是非常快的,但是做保存和删除操作比较慢了.

在Java7之前,即使使用new ArrayList创建对象,一个元素都不存储,但是在堆空间依然初始化了长度位10的Object数组,没必要.

从Java7开始优化这个设计,new ArrayList,其实底层创建的使用一个空数组.

 Object [] elementData = new Object[]{};

在第一次调用add方法的时候,才会重新去初始化数组.

 

链表:

链表结构(火车和火车车厢):

    1):单向链表:只能从头遍历到尾/只能从尾遍历到头.

    2):双向链表:既可以从头遍历到尾,又可以从尾遍历到头.

-------------------------------------

通过引用来表示上一个节点和下一个节点的关系

 

Java基础(三)

 

Java基础(三)

需要在Node中添加一个构造方法

给当前ele进行赋值

public Node(Object ele){

       this.ele = ele;

}

Java基础(三)

 

重写toString方便打印

 

 

Java基础(三)

Java基础(三)

LinkedList基于双向链

初始化时, 有个header  entry 值都null

使用header的优点:在任何一个条目(包括第一个和最后一个),都可以有一个前置条目

或一个后置条目,插入都会比较快,可以直接在开头和末尾添加元素

ArrayList:查询,更改较快,新增和删除较慢.

LinkedList:查询,更改较慢,新增和删除较快.

 

 

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙。

      散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。比如我们存储70个元素,但我们可能为这70个元素申请了100个元素的空间。70/100=0.7,这个数字称为负载(加载)因子。我们之所以这样做,也 是为了“快速存取”的目的。我们基于一种结果尽可能随机平均分布的固定函数H为每个元素安排存储位置,这样就可以避免遍历性质的线性搜索,以达到快速存取。但是由于此随机性,也必然导致一个问题就是冲突。所谓冲突,即两个元素通过散列函数H得到的地址相同,那么这两个元素称为“同义词”。这类似于70个人去一个有100个椅子的饭店吃饭。散列函数的计算结果是一个存储单位地址,每个存储单位称为“桶”。设一个散列表有m个桶,则散列函数的值域应为[0,m-1]。  

Java基础(三)

 

这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置

 

可是当哈希表接近装满时,因为数组的扩容问题,性能较低(转移到更大的哈希表中).

Java默认的散列单元大小全部都是2的幂,初始值为16(2的4次幂)。假如16条链表中的75%链接有数据的时候,则认为加载因子达到默认的0.75。HahSet开始重新散列,也就是将原来的散列结构全部抛弃,重新开辟一个散列单元大小为32(2的5次幂)的散列结果,并重新计算各个数据的存储位置。以此类推下去.....

负载(加载)因子:0.75.-->hash表提供的空间是16 也就是说当到达12的时候就扩容

 

排重机制 

假如我们有一个数据(散列码76268),而此时的HashSet有128个散列单元,那么这个数据将有可能插入到数组的第108个链表中(76268%128=108)。但这只是有可能,如果在第108号链表中发现有一个老数据与新数据equals()=true的话,这个新数据将被视为已经加入,而不再重复丢入链表。

直接根据数据的散列码和散列表的数组大小计算除余后,就得到了所在数组的位置,然后再查找链表中是否有这个数据即可。查找的代价也就是在链表中,但是真正一条链表中的数据很少,有的甚至没有。几乎没有什么迭代的代价可言了。所以散列表的查找效率建立在散列单元所指向的链表中的数据要少 。

哈希表的插入和查找是很优秀的.

 

Map集合

映射的数学解释:

设A、B是两个非空集合,如果存在一个法则f,使得对A中的每个元素a,按法则f,在B中有唯一确定的元素b与之对应,则称f为从A到B的映射,记作f:A→B。

Java基础(三)

 

-------------------------------------------------------------

映射关系(两个集合):A集合和B集合.

   A集合中的每一个元素都可以在B集合中找到唯一的一个值与之对应.

-------------------------------------------------------------

严格上说,Map并不是集合,而是两个集合之间的映射关系(Map接口并没有继承于Collection接口),然而因为Map可以存储数据(每次存储都应该存储A集合中以一个元素(key),B集合中一个元素(value)),我们还是习惯把Map也称之为集合.

-------------------------------------------------------------

因为:Map接口并没有继承于Collection接口也没有继承于Iterable接口,所以不能直接对Map使用for-each操作.

 

ps:1.key(键)必须唯一

   2.value(值)可以不唯一      

   例如: key1 = value1

       key2 = value1

  如下不行:

       key1 = value1

       key1 = value2

斗地主发牌

/**

 * 扑克牌类

 * @author JKMaster

 *

 */

public class Poker {

  //表示存储的花色和点数

  private static final String[] color = {"♥","♦","♠","♣"};

  private static final String[] num = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};

  private static final String[] king = {"大�","小�"};

  

  //存储所有的牌

  private static List<String> list = new ArrayList<>();

  

  //存储牌

  public static void setPoker() {

  for(int i =0;i<color.length;i++) {//花色

  for(int j = 0;j<num.length;j++) {//点数

  list.add(color[i]+num[j]);

  

  }

  if(i<king.length) {

  list.add(king[i]);

  }

  }

  }

  

  //洗牌

  public static void flushPoker() {

  Collections.shuffle(list);

  }

  

  

  //发牌

  public static void dealPoker(List<String> p1List,List<String> p2List,List<String> p3List,List<String> p4List) {

  //循环遍历操作集合中的元素下标,操作了集合集合中的元素

  for(int i  = 0;i<list.size();i++) {

  if(i<list.size()-3) {

if (i % 3 == 0) {

p1List.add(list.get(i));

} else if (i % 2 == 0) {

p2List.add(list.get(i));

} else {

p3List.add(list.get(i));

}

 }else {

 p4List.add(list.get(i));//最后留给地主的3牌

 }

  }

  }

public class Player {

private String name;

// 存储玩家手里的牌

private List<String> pokers = new ArrayList<>();

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public List<String> getPokers() {

return pokers;

}

 

public void setPokers(List<String> pokers) {

this.pokers = pokers;

}

 

public Player() {

super();

// TODO Auto-generated constructor stub

}

 

public Player(String name) {

super();

this.name = name;

this.pokers = pokers;

}

 

//打印玩家手里的牌

public void showInfosPoker() {

System.out.println(name+":"+pokers);

}

 

}

 

public class Relu implements Comparator<String> {

 

@Override

public int compare(String o1, String o2) {

//定义两个Integer类型存储 转换后的值进行比较

Integer i1;

Integer i2;

//点数和花色进行拆分

//"2","3","4","5","6","7","8","9","10","J","Q","K","A" "�","�"

String str1 = o1.substring(1);

String str2 = o2.substring(1);

 

if(str1.equals("J")) {

i1 = 11;

}else if(str1.equals("Q")) {

i1 = 12;

}else if(str1.equals("K")) {

i1 = 13;

}else if(str1.equals("A")) {

i1 = 14;

}else if(str1.equals("�")) {

i1 = 15;

}else if(str1.equals("�")) {

i1 = 16;

}else {

i1 = new Integer(str1);

}

 

if(str2.equals("J")) {

i2 = 11;

}else if(str2.equals("Q")) {

i2 = 12;

}else if(str2.equals("K")) {

i2 = 13;

}else if(str2.equals("A")) {

i2 = 14;

}else if(str2.equals("�")) {

i2 = 15;

}else if(str2.equals("�")) {

i2 = 16;

}else {

i2 = new Integer(str2);

}

return i1 - i2;

}

 

}

public class Test {

     public static void main(String[] args) throws InterruptedException {

System.out.println("------------------------------------JJ斗地主----------------------------------------");

System.out.println("正在洗牌.....");

Poker.setPoker();

Poker.flushPoker();

Thread.sleep(1000); //让当前线程睡眠,卡顿效果 毫秒单位

 

Scanner input = new Scanner(System.in);

System.out.println("请输入三个玩家的姓名:");

String name1 = input.next();

String name2 = input.next();

String name3 = input.next();

 

//存储3个玩家手里的扑克牌

List<String> p1List = new ArrayList<>();

List<String> p2List = new ArrayList<>();

List<String> p3List = new ArrayList<>();

//存储剩余的3张牌

List<String> p4List = new ArrayList<>();

 

System.out.println("进入发牌阶段......");

        Poker.dealPoker(p1List, p2List, p3List, p4List);

        Thread.sleep(1000); //������� --> ���ٵ�Ч��

 

        //玩家手里牌进行排序

        Collections.sort(p1List,new Relu());

        Collections.sort(p2List,new Relu());

        Collections.sort(p3List,new Relu());

        

        //将牌设置给玩家

        Player  p1 = new Player(name1);

        Player  p2 = new Player(name2);

        Player  p3 = new Player(name3);

        p1.setPokers(p1List);

        p2.setPokers(p2List);

        p3.setPokers(p3List);

        

        System.out.println("展示玩家的手牌:");

        p1.showInfosPoker();

        p2.showInfosPoker();

        p3.showInfosPoker();

        

        System.out.println("请输入要叫地主玩家的姓名:");

        String name4 = input.next();

        System.out.println("底牌是:"+p4List);

        if(p1.getName().equals(name4)) {

         p1List.addAll(p4List);

         Collections.sort(p1List,new Relu());

        }else if(p2.getName().equals(name4)) {

         p2List.addAll(p4List);

         Collections.sort(p1List,new Relu());

        }else {

         p3List.addAll(p4List);

         Collections.sort(p1List,new Relu());

        }

        

        

        System.out.println("展示玩家的手牌:");

        p1.showInfosPoker();

        p2.showInfosPoker();

        p3.showInfosPoker();

 

相关文章:

  • 2022-12-23
  • 2021-07-27
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-10
猜你喜欢
  • 2021-09-11
  • 2022-01-16
  • 2021-09-07
  • 2021-11-29
相关资源
相似解决方案