基本排序算法、查找算法、链表的实现、集合框架回顾(Java学习)

基本排序算法

Java中常见的排序算法有7种:冒泡、插入、选择、快速、希尔、归并和堆

冒泡排序

核心思想是:相邻比较,交换位置

时间复杂度O(n**2),空间复杂度O(1),稳定的

public class Test1 { 
    public static void main(String[] args) { 
        int[] arr = new int[10];
        Random r=new Random(); 
        for(int i=0;i<arr.length;i++) 
            arr[i]=r.nextInt(100); 
        System.out.println(Arrays.toString(arr)); 
        //冒泡排序 
        for(int i=1;i<arr.length;i++){ 
            for(int k=0;k<arr.length-i;k++){ 
                if(arr[k]>arr[k+1]){ 
                    int temp=arr[k]; 
                    arr[k]=arr[k+1]; 
                    arr[k+1]=temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr)); 
    } 
}
快速排序

思路:通过一次排序将序列分为左右两部分,其中左半部分的值都小于右半部分的值,然后再对左右部分的数据进行排序,直到所有数据都有序

总结:时间复杂度O(NlogN),空间复杂度为O(1),不稳定

public class Test2 { 
    public static void main(String[] args) { 
        int[] arr = new int[10]; 
        Random r = new Random(); 
        for (int i = 0; i < arr.length; i++) 
            arr[i] = r.nextInt(100); 
        System.out.println(Arrays.toString(arr));
        quickSort(arr, 0, arr.length - 1); 
        System.out.println(Arrays.toString(arr)); 
    }
    public static void quickSort(int[] arr, int low, int high) { 
        if (low >= high)
            return; 
        int pos = part(arr, low, high); 
        quickSort(arr, low, pos - 1); 
        quickSort(arr, pos + 1, high); 
    }
    public static int part(int[] arr, int low, int high) { 
        int key = arr[low]; 
        while (low < high) { 
            while (low < high && arr[high] >= key) 
                high--;
            arr[low] = arr[high]; 
            while (low < high && arr[low] <= key) 
                low++; 
            arr[high] = arr[low]; 
        }
        arr[low] = key; 
        return low; 
    } 
}

查找算法

Java中常见的查找算法:顺序查找、折半查找、二叉树、哈希表、分块查找

顺序查找

时间复杂度O(n)

int[] arr={12,3,24,15,56}; 
int target=24; 
int pos=-1;//如果查找不到则返回-1 
for(int i=0;i<arr.length;i++){ 
    if(target==arr[i]){ 
        pos=i; 
        break;
    }
}
折半查找

前提:数据必须有序

时间复杂度为O(logN)

public class Test1 { 
    public static void main(String[] args) { 
        int[] arr = new int[11]; 
        Random r = new Random(); 
        for (int i = 0; i < arr.length - 1; i++) 
            arr[i] = r.nextInt(100); 
        arr[arr.length - 1] = 36; // 折半查找的前提是数据必须有序 
        Arrays.sort(arr); 
        System.out.println(Arrays.toString(arr));
        int pos=binarySearch(arr, 34); 
        System.out.println(pos); 
    }
    public static int binarySearch(int[] arr, int key) {
        int min = 0; 
        int max = arr.length - 1; 
        int mid = -1;
        while (min <= max) { 
            mid = (min + max) >> 1; 
            if (key > arr[mid]) 
                min = mid + 1; 
            else if (key < arr[mid]) 
                max = mid - 1; elsereturn mid; }return -1; 
    }
}

链表的实现

线性表在一个序列中除去头尾元素,每个元素都有一个直接前驱和直接后续,头没有前驱,尾没有后续有数组和链表两种实现

  • 数组:物理上的连续存放、支持随机访问、读快但是增删慢

  • 链表:物理上并不会连续存放、不支持随机访问、读慢但是增删快

  • 如果频繁进行增删优先考虑使用链表,如果频繁进行随机访问优先考虑使用数组

class Node{ 
    private int data;//具体存储数据 
    private Node next;//指向下一个元素的指针 
}
链表和数组对比

数组使用连续的内存空间存储数据,可以有效地利用CPU缓存机制,预读数组中的数据,从而提高访问效率;链表在内存中不连续,没有办法支持预读处理,对CPU缓存不友好

数组大小固定,一旦声明就占用整块的连续内存空间,扩容复制非常耗时。链表不需要额外的存储空间【int】,链表中的元素Node需要额外的存储空间,会造成一定程度上的内存空间浪费,而且频繁的内存申请和释放,容易产生内存碎片

集合框架回顾

Collection接口:无序、允许重复,顶级接口(Iterable接口)

  • List接口是Collection接口的子接口,有序、允许重复

    • ArrayList、Vector和LinkedList
  • Set接口是Collection接口的子接口,无序、不允许重复

    • HashSet、LinkedHashSet、TreeSet
数组和集合的区别
  • 长度的区别:数组长度固定,集合可变

  • 内容的区别:数组可以是基本类型,也可以是引用类型;集合中只能是引用类型

  • 元素内容:数组只能存储同一类型,集合中可以存储不同的数据类型

Collection接口中的方法
  • add(E e):boolean在集合末尾追加元素

  • remove(E e):boolean删除指定的元素

  • clear():void 清空

  • contains(Object):Boolean判断是否包含指定元素

  • isEmpty():boolean 判断集合为空

  • size():int元素个数

  • iterate():Iterator迭代集合中的所有元素

  • toArray():Object[]

遍历集合中的所有元素

for(Object tmp:collection){}

使用迭代器

Iterator it=collection.iterator(); 
while(it.hasNext()){ 
    Object tmp=it.next(); 
}
List接口
  • add(int index,Object obj):void在指定位置上添加元素

  • get(int index):object可以获取位置上的元素

  • remove(int index):Object 删除指定位置上的元素,并返回删除的数据

  • set(int index,Object obj):Object 修改指定位置上的元素,并返回原始数据

  • indexOf(Object):int查找元素的下标位置

实现类

ArrayList底层实现是数组,查询快、增删慢,线程不安全,效率高,可以存储重复元素

LinkedList底层实现是双向链表,查询慢、增删快【定位位置O(n)】,线程不安全,效率高,可以存储重复元素

Vector底层实现数组,查询快、增删慢,线程安全,效率较低,可以存储重复元素

ArrayList

内部实现是数组,实现了RandomAccess接口,支持随机访问功能,不是一个线程安全的容器

  • 具体元素的移动和拷贝都是通过System.arrayCopy实现的

构造器

ArrayList()内部存储数据的数组为空数组

  • elementData保存数据

  • capacity容器 ArrayList(int),默认容积10

  • 当容器容积不足时,会自动进行扩容处理,容积增大50%

  • modcount快速失败

add方法

添加元素时首先仅从范围检查,然后和建议分配的大小值进行比较,如果大于默认大小则进行扩容。扩容时首先将原始数组的大小提升到1.5倍,称为新数组大小,然后进行元素的拷贝

remove方法

线程安全的替代方案:Collections.sychronizedList CopyOnWriteArrayList

LinkedList

双向链表,没有长度限制

删除remove(Object)虽然删除操作时间复杂度为O(1),但是定位元素的时间复杂度为O(n)

练习题

输入一个链表,反转链表后,输出新链表的表头

public ListNode reverseList(ListNode head){ 
    if(head==null) 
        return null; //判断链表是否为空,为空的化直接返回null
    ListNode prev=null; //前一个结点 
    ListNode next=null; //后一个结点 
    while(head!=null){ 
        next=head.next; 
        head.next=prev; 
        prev=head; 
        head=next; 
    }
    return prev; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值