JAVASE 总结作业五

一、数组排序

1. 冒泡排序

每两个元素比较,按照从小到大顺序时,两两找出较大值,可能会发生交换,将较大值放在右侧,按照从大到小顺序时,两两比较找出较小值,可能会发生交换,将较小值放在右侧

代码实现

// TODO 冒泡排序

int[] a = { 34, 23, 77, 66, 3, 145 };

// 排序的次数:数组元素的个数减一

for (int i = 0; i < a.length - 1; i++) {

// j的取值为当前数组能够取到的下标减去已经排好的数(已经执行排序的次数)

for (int j = 0; j < a.length - 1 - i; j++) {

// 两个数字的比较,是否交换

// 从左至右,从小到大

if (a[j] > a[j + 1]) {

a[j] = a[j] ^ a[j + 1];

a[j + 1] = a[j] ^ a[j + 1];

a[j] = a[j] ^ a[j + 1];

}

}

}

2. 选择排序

冒泡算法的改进,每次从当前比较的一组数中选出最值,排好一个数,只进行一次交换

代码实现

// TODO 选择排序

int[] a = { 34, 23, 77, 66, 3, 145 };

// 排序的次数:数组元素的个数减一

for (int i = 0; i < a.length - 1; i++) {

// 每次指向a[0]

int max = 0;

// j的取值为当前数组能够取到的下标减去已经排好的数(已经执行排序的次数)

for (int j = 1; j < a.length - i; j++) {

// 使用max记录当前比较中较大的数

// 从左至右,从小到大

if (a[j] > a[max]) {

max = j;

}

}

// 将当前获取到的较大的数放在相应的位置

// a ^ a = 0(亦或运算->相同为0,不同为1)

if (max != a.length - i - 1) {

/*int temp = a[max];

a[max] = a[a.length - i - 1];

a[a.length - i - 1] = temp;*/

a[max] = a[max] ^ a[a.length - i - 1];

a[a.length - i - 1] = a[max] ^ a[a.length - i - 1];

a[max] = a[max] ^ a[a.length - i - 1];

}

}

3. Arrays工具类

Arrays所在包:java.util

sort方法:将数组的元素按照自然序列排序(基本数据类型),也可以自定义排序规则

使用规则:无返回值类型,直接传入数组变量作为参数

int a[] = {25,66,7,8,43,200}

Arrays.sort(a);

二、数组查找(二分法)

在一个有序数组中查找一个数,返回其所在位置

代码实现

// TODO 有序数组的二分查找

int[] a = {3,20,10,5,67,103};

Arrays.sort(a);

for (int i : a) {

System.out.print(i + " ");

}

System.out.println();

System.out.println("请输入要查找的数:");

Scanner scanner = new Scanner(System.in);

int n = scanner.nextInt();

// 初始化用于标记区间的变量

int left = 0;

int right = a.length - 1;

// 初始化每次用于比较的变量的下标

int middle = (left + right) / 2;

// 标记是否已经找到相应的数字

int location = -1;

while(left <= right) {

if (a[middle] == n) {

// 找到时标记位置,并且跳出

location = middle;

break;

}else if (n > a[middle]) {

// 在右侧区间中,将left指标右移

left = middle + 1;

middle = (left + right) / 2;

}else {

// 在左侧区间中,将right指标左移

right = middle - 1;

middle = (left + right) / 2;

}

}

if (location != -1) {

System.out.println("位置为" + (location + 1));

}else {

System.out.println("数组中没有该元素");

}

scanner.close();

三、数组扩容

数组定义后长度固定,可以新建一个数组,迁移原数组数据,并提供更多的空间放入新数据

ArrayList的add方法(用于向集合中添加新的元素):ArrayList底层通过数组结构实现,过程与数组扩容步骤类似

代码实现

public static void main(String[] args) {

// TODO 数组扩容

/* 用户从控制台不断的录入数据,当数据录入的个数已经超过数组容量时

可以自动扩容,继续接受元素->ArrayList add()方法源码(10)

定义一个数组(a),例如长度为5

定义一个变量,记录用户输入了几个数据,即数组(a)中已经添加了几个元素

每次用户输入数据时,使用变量判断是否超出了当前数组(a)的长度

如果超出,定义一个新的数组(b),复制原来数组中的数据到新数组(b)

将新输入的元素添加到数组(b)中,并将新数组赋值给原数组(a)

Scanner scanner = new Scanner(System.in);

控制是否继续输入数据 */

boolean flag = true;

// 标记数组当前存储元素的个数

int index = 0;

while(flag) {

System.out.println("请输入一个数");

int number = scanner.nextInt();

if (index == a.length) {

extend();

}

a[index ++] = number;

scanner.nextLine();

System.out.println("是否继续输入y/n");

String input = scanner.nextLine();

if ("y".equals(input)) {

flag = true;

}else {

flag = false;

}

}

for (int number : a) {

System.out.println(number);

}

scanner.close();

}

/**

* 将原数组数据保留下来,并扩充空间

*/

public static void extend() {

int[] b = new int[a.length + 1];

for (int i = 0; i < a.length; i++) {

b[i] = a[i];

}

a = b;

}

查找算法
查找算法分类:
  1)静态查找和动态查找;
    注:静态或者动态都是针对查找表而言的。动态表指查找表中有删除和插入操作的表。
  2)无序查找和有序查找。
    无序查找:被查找数列有序无序均可;
    有序查找:被查找数列必须为有序数列。
平均查找长度(Average Search Length,ASL):
需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。
  对于含有n个数据元素的查找表,查找成功的平均查找长度为:ASL = Pi*Ci的和。
  Pi:查找表中第i个数据元素的概率。
  Ci:找到第i个数据元素时已经比较过的次数。
顺序查找
基本思想:顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;若扫描结束仍没有找到关键字等于k的结点,表示查找失败
代码实现
 /**
     * 顺序查找
     * 顺序查找的时间复杂度为O(n)。
     * @param arr
     * @param k
     * @param value
     * @return
     */
    public static  int Search(int[] arr,int k,int value){
        for (int i = 0; i < k; i++) {
            if (value == arr[i])
                return i;
        }
        return  -1;
    }

二分查找
基本思想:也称为是折半查找,属于有序查找算法。用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表,若相等则查找成功;若不相等,再根据k与该中间结点关键字的比较结果确定下一步查找哪个子表,这样递归进行,直到查找到或查找结束发现表中没有这样的结点
代码实现
 /**
 *二分查找必须是有序的,本方法中必须是升序排列
 *最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n)
 */
 //折半查找
    public static int search1(int[] arr,int value,int k){
        int low,mid,heigh;
        low=0;
        heigh=k-1;
        while (low<=heigh){
            mid=(low+heigh)/2;
            if (value == arr[mid])
                return mid;
            if (value<arr[mid])
                heigh=mid-1;
            if (value>arr[mid])
                low=mid+1;
        }
        return -1;
    }
    //迭代
    public static int search2(int[] arr,int value,int low,int heigh){
        if (low>heigh)
            return -1;
        int mid=(low+heigh)/2;
        if (value==arr[mid])
            return mid;
        if (value<arr[mid])
            return search2(arr,value,low,mid-1);
        if (value>arr[mid])
            return search2(arr,value,mid+1,heigh);
        return -1;
    }
 

哈希查找
基本思想
哈希的思路很简单,如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。

步骤思路
1)用给定的哈希函数构造哈希表;
  2)根据选择的冲突处理方法解决地址冲突;
    常见的解决冲突的方法:拉链法和线性探测法。详细的介绍可以参见:浅谈算法和数据结构: 十一 哈希表。
  3)在哈希表的基础上执行哈希查找。
  哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和空间上做出取舍。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值