数据结构重点复习
前言
排序
快速排序:
将记录放在中间,左边都是小的,右边都是>=的,划分好左右递归快排左右。
复杂度:最好的情况二分,那种每次都是平均两份,一共logN次,每次N,O(NlogN),所以最差NN
稳定性:每次和中轴交换,不稳定
代码:
public class Solution{
public void quicksort(int[] a,int left,int right){
if(a.length==0||left>right)
return;
int base = a[left];
int i = left;
int j = right;
while(i<j){
while(a[j]>=base && i<j)
j--;
while(a[i]<=base && i<j)
i++;
//交换
swap(a[i],a[j]);
}
//此时左右指针相遇,由于先让右指针移动,所以当前节点一定是<base的
a[left] = a[i];
a[i] = base;
quicksort(a,left,i-1);
quicksort(a,i+1,right);
}
}
归并排序:
适合多链表排序合并,左归并,右归并,然后借助temp[]合并进入后移回数组。因为是二路有序的归并,最好最坏的复杂度都是O(NlogN)
最大的好处是这是一个稳定的排序
但是需要O(n)的空间
public class Solution{
public void mergesort(int[] a,int left,int right,int[] temp){
while(left < right){
int mid = (left+right)/2;
mergesort(a,left,mid,temp);
mergesort(a,mid+1,right,temp);
merge(a,left,mid,right,temp);
}
}
public void Merge(int a[],int left,int mid,int right,int[] temp){
int i = left,j=mid+1;
int t=0;
while(i<=mid && j<=right){//向temp数组归并
if(a[i] <a[j])
temp[t++] = a[i++];
else
temp[t++] = a[j++];
}
//剩下的复制到temp
while(i<=mid)
temp[t++] = arr[i++];
while(j<=right)
temo[t++] = arr[j++];
//放回原数组
i=0;
while(left <= right)
arr[left++] = temp[t++];
}
}
堆排序:
利用完全二叉树的父子节点的下标关系,父节点>=子节点就是大根堆
不断调整堆,不稳定的,最好最坏都是nlogn
就在数组上模拟堆,所以空间是1
public class Solution{
public void heapSort(int[] a){
int i,n=a.length;
for(i=n/2-1;i>=0;i--)
heapAjust(a,i,n);//初始化
for(i=n-1;i>0;i--){//每次取堆头放入数组末尾,然后重新调整为大顶堆
swap(a,i);//
heapAjust(a,0,i-1);
}
}
//核心函数,完成将以i指向的i对应的非叶子节点的树调整成大顶堆。注意这个树中i+1-n是正确的大根堆,只有根节点i不对,往下调整,把它降下去,大的升上来。
//i表示非叶子节点在数组中的索引
//表示对多少个元素进行调整,len实在逐渐减少的
public void heapAjust(int[] a,int i,int len){
int temp = k[i];//取出当前变量的值,保存
for(int j=i*2+1;j<len;j=j*2+1)//从根节点左孩子开始,下次变成左孩子的左孩子{
if(j+1<len && a[j] < a[j+1])//如果左孩子小于右孩子{
j++;//右孩子更大,要右孩子
}
if(a[j] > temp){//左右孩子中大的那个比当前老大temp还大
a[i] = a[j];//把较大的值给当前节点,注意当前节点是i,不是j哦
i= j;//更新当前节点,开始调整i调整后的位置
}else{//如果temp就是最大的,当前i调整好了,整个树叶调整好了
break;
}
}
}
}
希尔排序
一种高级一点的插入排序,设置一个增量interval=n,每次interval/2,直到为1为止,对于每个增量我们从interval开始,到n结束的每个元素,按照interval的步长和前面的元素比较,后移,插入。
时间就是O(Nlogn),
空间没用。
下面是三种简单的排序
(1)直接插入排序——什么叫直接插入呢?意思就是每次把新元素添加到已经拍好序的数组中,(向前找比他大的)插入前要后移。
最好的情况就是:已经有序了,我只要比较n次O(n)
最坏的情况是:逆序了已经,每个元素要比较,还要移动元素,O(nn)
这中排序是稳定的。
(2)冒泡排序——它的思想是这样的,要从前往后拍好序,每次只能当前元素。从最后一个元素开始,到当前元素为止,如果后一个元素<前一个元素,交换。如果有一次比较的过程中没有发生过交换,成功了。
最好:正数有序,只要比较n次O(n)
最坏:逆序有序,要比较nn-1***1,O(nn)
是稳定的排序
(3)直接选择排序——从未排序的元素中找到最小的元素,交换到第一个未排序的位置。
最好最坏:都要比较O (nn)次,找最小
稳定性:存在和前面元素的交换,不稳定的。
二分查找
int binarySearch(vector<int> nums, int val)
{
int low = 0, high = nums.size() - 1, mid;
while (low <= high)//小于等于都可以找
{
mid = (low + high) / 2;
if (nums[mid] == val)
{
return mid;
}
else if (nums[mid] > val)
{
high = mid - 1;
}
else
low = mid + 1;
}
return -1;
}
树相关
BST树的删除节点
首先要找到那个节点
- 如果是单身节点,直接删除
- 只有左或者右子树,孩子接到父亲那里
- 有左子树也有右子树:把右子树最小的元素替换到待删除的位置,然后删除那个最小元素
public boolean delete(Node root,int value){
if(root==null)
return false;
if(value==root.value){
if(root.left==null){
root.value = root.right.value;
root.right = root.right.right;
}else if(root.right==null){
root.value = root.left.value;
root.left = root.left.left;
}else{
//找到右子树的最左节点rightMin和它的父节点rightMinFather
//让rightMinFather来接收rightMin的右孩子,作为rightMinFather的left,当然前提是rightMinFather 不等于root,
if(rightMinFather不等于root)
rightMinFather.left = rightMin.right;
else
root.right = rightMin.right;
root.value = rightMin.value;
root.right = rightMin.right;
}
return true;
}else if(value<root.value)
return delete(root.left,value);
else
return delete(root.right,value);
}
B树和B+树
(1)前言
其实他们包括红黑树、BST都是一种名为 动态查找树的东东,但是呢BST是二叉的,查找时间和深度有关。
但是在有大规模数据的情况下,我们需要用索引来查找,那么像是二叉查找树这种结构就不行了,很可能因为树的深度过高儿导致(外存)磁盘读写过于频繁,效率低下。所以——多叉的查找树就诞生了。
(1)首先什么是B树呢?
最大的特点是——孩子多,所以可以做数据库系统的结构。
- 每个节点最多m个孩子
- 除了跟节点,其他每个分支节点至少有m/2课子树
- 老大,也就是跟至少也要有两个孩子
- 每个节点的孩子指针之间夹杂着一个关键码(递增)
- 叶子在同一层,不包含任何信息
如图:假如我们要找的是29,首先读跟节点所在磁盘块找到17和35之间,然后再读磁盘找到在26和30之间,再次读磁盘块找到了。
B树孩子多,所以呢高度不会过分,高度大约是log以m/2为底(N/2)
(3)那什么是B+树呢
是B树的一种变形,它不同的地方中最重要的一点是它的叶子中是包含着全部的关键字的信息的,并且叶子节点本身还按照顺序链接起来了,非叶子节点保存的只是子树的最大或最小值,就是那种索引的感觉。
B+树比B树更适合查找大数据量
原因:内部节点不保存数据,只保存了关键字,内部节点就精简了,我们可以把这些内部节点放在同一个磁盘块上,一次性就读到了,IO大大减少。
还有一个原因就是查找的效率更稳定,数据都是放在叶子节点的,不管找谁都是从跟到叶子,大家走的路长度相同。不像是B树有的数据保存在内部节点,有的查的快,有的查的慢。
红黑树
图相关
最短路径算法——迪杰斯特拉
关键路径和拓扑排序
LRU(最近最少使用算法)
判断一个数是不是整数
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。