补漏

**

排序算法:

**
快排(python):

def quick_sort(a,low,high):
    start = low
    end = high
    key = a[low]

    while(end > start):#此处控制循环不停的迭代
        # (第一次)从后往前
        while start < end and key <= a[end]:
            end = end -1
        if(key >= a[end]):
            tmp = a[start]
            a[start] = a[end]
            a[end] = tmp
        #(第一次)从前往后
        while start < end and key >= a[start]:
            start = start + 1
        if(a[start] >= key):
            tmp = a[end]
            a[end] = a[start]
            a[start] = tmp
        print('start:'+str(start)+'\t'+'end:'+str(end))
      #此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
    if(start > low):
        quick_sort(a,low,start-1)
    if(end < high):
        quick_sort(a,end+1,high)
    return a

冒泡排序:先从数组中找到最大值(或最小值)并放到数组最左端(或最右端),然后在剩下的数字中找到次大值(或次小值)
过程中不重新定义其他参数,只是元素的两两比较

// 冒泡排序
void BubbleSort(int arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length -  i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp;
				temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

选择排序:每一趟在n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。

// 选择排序
void SelectionSort(int arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		int index = i;
		for (int j = i+1; j < length; j++)
		{
			if (arr[j] < arr[index])
			{
				index = j;
			}
		}
		if (index == i)
			continue;
		else
		{
			int temp;
			temp = arr[index];
			arr[index] = arr[i];
			arr[i] = temp;
		}
	}
}

**

查找算法:

**
二分查找(排序的数组必须是有序的):

def binary_search(a,key):#升序排列
    len_ = len(a)
    if len_ < 1:
        return False

    mid =  len_ // 2
    if key < a[mid]:
        return binary_search(a[:mid],key)
    elif key > a[mid]:
        return binary_search(a[mid+1:],key)
    else:
        return True

if __name__ == '__main__':
    lis = [2,4, 5, 12, 14, 23]
    if binary_search(lis, 15):
        print('ok')

**

Java专栏

**
HashMap工作原理:
HashMap(非同步、线程不安全)
1、允许使用null键和null值
2、影响HashMap实例的两个参数:初始容量和加载因子
HashMap的数据结构:数组+链表组成;寻址容易,插入和删除容易
HashMap事实上是一个线性的数组实现的,所以能够理解为其存储数据的容器是一个线性容器
HashMap里面有一个内部静态类Entry,其重要的属性有key、value、next;Entry是键值对实现的一个基础bean。也就是说HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存
在Entry[]中;
数组的作用是存储链表中第一个节点的地址值。
在这里插入图片描述
当哈希表中条目数超过了当前容量与加载因子的乘积时,哈希表将会作出自我调整,将容量扩充为原来的两倍,并且重新将原有的元素重新映射到表中,
看不懂?那就再看看下面的
HashMap存取实现
存储算法:
int hash=key.hashcode();
int index=hash%Entry[].length;//获得数组下标:key的hash值对Entry数组长度进行取余
Entry[index]=value;
注意:假设两个key通过hash%Entry[].length得到的index同样,会不会覆盖?
是不会的。Entry类有一个next属性,作用是指向下一个Entry。打个例如, 第一个键值对A进来。通过计算其key的hash得到的index=0。记做:Entry[0] = A。一会后又进来一个键值对B,通过计算其index也等于0,如今怎么办?HashMap会这样做:B.next =A,Entry[0] = B,假设又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方事实上存取了A,B,C三个键值对,他们通过next这个属性链接在一起。
取值算法:
获取key的hashcode值,通过hash值去计算hash%Entry[].length,获取Entry[hash%Entry[].length],定位到该数组元素之后,再遍历该元素处的链表。
再哈希,其目的是为了减少哈希冲突,使元素能够均匀的分布在数组上,从而提高数组的存取效率。

当返回为 null 时,你不能判断是没有找到指定元素,还是在hashmap 中存着一个value为 null 的元素,因为hashmap允许value为 null.

重点:碰撞探测
当两个对象的hashcode相同时(他们本身可能并不同),他们的bucket位置是一样的。因为HashMap使用链表存储对象,这个Entry会存储在链表中。在取值的时候,将会遍历链表找到值对象。怎么着?找到bucket位置之后,调用key.equals()方法会找到链表中正确的节点。

总结:HashMap是基于hashing原理对key-value对进行存储与获取,当使用put()方法添加key-value对时,它会首先检查hashCode的值,并以此获得对应的bucket位置进行存储,当发生冲突时(hashcode值相同的两个不同key),新的key-value对会以结点的形式添加到链表的末尾。而使用get()方法时,同样地会根据key的hashCode值找到相应的bucket位置,再通过key.equals()方法找到对应的key-value对,最终成功获取value值。

优化:
使用不可变的、声明作final的对象(比如,String是不可变类,也是final的而且也重写了equals()和hashcode()方法),并且采用合适的equals()和hashcode()方法的话,将会减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度。

如果HashMap的大小超过了负载因子定义的容量,怎么办?
在HashMap中,还存在着两个概念:桶(buckets)和加载因子(load factor)
默认的负载因子大小为0.75,也就是说当一个map填满了75%的bucket时,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这一过程称为rehash。

重新调整HashMap大小存在什么问题?
在多线程发现HashMap需要重新调整大小时,他们会试着调整大小。在调整大小的过程中,存储在链表中的元素会反过来,因为在移植到新的bucket时,HashMap会将元素放在头部。如果条件竞争了,就会出现死循环。但是多线程为啥要用HashMap?

HashMap、HashTable、ConcurrentHashMap的线程安全问题
HashMap:线程不安全。HashMap的key和value都可以为null值。key=null的键只能有一个;value=null可以有多个,表示HashMap中没有该键或者表示该键对应的值为null;所以HashMap中应该用containsKey()方法来判断是否有该键。
HashTable:锁住整张hash表,让线程独占。synchronized是针对整张表的,即每次锁住整张表。安全的背后是巨大的浪费。HashTable的key和value都不可以为null。
ConcurrentHashMap:一个更快的HashMap,它提供了好得多的并发性。ConcurrentHashMap锁的方式是细粒度的。ConcurrentHashMap将hash表分为16个桶,get、put、remove等操作只需要锁需要用到的桶。
Map m = Collections.synchronizedMap(new HashMap(…));

Java StringBuilder StringBuffer String
运行速度:StringBuilder > StringBuffer > String
String最慢的原因:String是字符串常量,StringBuilder和StringBuffer是字符串变量;String创建后是不可以变的,而StringBuilder和StringBuffer是可以变的。
在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的。
最终总结:
String:适合少量的字符串操作
StringBuilder:适合单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适合多线程下在字符缓冲区进行大量操作的情况
StringBuilder和StringBuffer,字符串都是存放在char[]中的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值