1、哈希散列值的计算平均查找长度
哈希表的构造方法:
(1)、数字分析法:事先知道关键字的集合,且每个关键字的位数比哈希表的地址码位数多时,可以从关键字中选出分布比较均匀的若干位,构成哈希地址。
(2)、平方取中法:当无法确定关键字中哪几位分布比较均匀时,可以先求出关键字的平方值的中间几位作为哈希地址
(3)、分段叠加法:按哈希表的地址位数将关键字分成位数相等的几部分(最后一部分较短),然后将这几部分相加,舍弃最高位后的结果就是该关键字的哈希地址。
(4)、除留余数法:假设哈希表长为 m,p为小于等于 m 的 最大数数,则哈希 函数为 H(k) = k%p
(5)、伪随机数为:采用一个伪随机函数作为哈希函数,即 H(key) = random(key)
哈希表处理冲突的方法:
(1)、开放定址法
(2)、再哈希法
(3)、链地址法
(4)、建立公共溢出区
哈希表的性能分析:
哈希法中影响关键字比较次数的因素有三个:哈希函数,处理冲突的方法,哈希表的装填因子。装填因子 a 的定义如下: a = 哈希表中元素的个数 / 哈希表的长度 a 可描述哈希表的装满程度。a 越小,发生冲突的可能性越小; a 越大 ,发生冲突的可能性越大。
哈希表的查找过程示例:
2、小根堆的应用
大根堆和小根堆排序,代码贴上:
/*************************************************************************
> File Name: HeapSort.cpp
> Author: arrayli
> Mail: [email protected]
> Created Time: 2018年03月27日 星期二 14时33分47秒
************************************************************************/
// 直接插入排序:
// 时间复杂度: O(nlog2n)
// 最好: O(nlog2n)
// 最欢情况: O(nlog2n)
// 空间复杂度: O(1)
// 稳定性: 稳定
#include<stdio.h>
// 将堆顶元素与末尾元素进行交换
template<typename T>
void Swap( T* arr,int heapTop,int heapTail )
{
T temp = arr[heapTop];
arr[heapTop] = arr[heapTail];
arr[heapTail] = temp;
}
// 调整大根堆
template<typename T>
void AdjustHeap(T *arr,int currentNode,int HeapLength)
{
int leftChild = 0,rightChild = 0 ,largest = 0;
leftChild = 2*currentNode + 1;
rightChild = 2*currentNode + 2;
// 判断 当前结点的左子节点是否大于当前结点,如果大于当前结点,则 largest = rightChild;
if(leftChild< HeapLength && arr[leftChild] > arr[currentNode])
largest = leftChild;
// 否则 largest = currentNode;
else
largest = currentNode;
// 然后判断当前结点的右子节点是否大于 largest
if(rightChild < HeapLength && arr[rightChild] > arr[largest])
largest = rightChild;
if(largest != currentNode)
{
// 交换最大结点和当前结点的值
// 即将堆顶元素与末尾元素进行交换
Swap(arr,currentNode,largest);
// 重新对堆进行调整
AdjustHeap(arr,largest,HeapLength);
}
}
// 构建大根堆
template<typename T>
void MaxHeapCreat(T *arr,int len)
{
int i = 0;
for( i = len/2;i>=0; i-- )
{
AdjustHeap(arr,i,len);
}
}
// 大根堆排序
template<typename T>
void HeapSort(T *arr,int len)
{
// 构建大根堆
MaxHeapCreat(arr,len);
for(int i = len-1;i>=0;i--)
{
// 交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
Swap(arr,0,i);
// 又一次调用堆顶点成为大根堆,仅仅有被交换的分支才有可能不是大根堆
AdjustHeap(arr,0,i);
}
}
template<typename T>
void print(T *arr,int len)
{
for(int i=0;i<len;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
int main(void)
{
int arr[] = {9,8,7,6,5,4,3,2,1,0};
int len = sizeof(arr)/sizeof(arr[0]);
print(arr,len);
HeapSort(arr,len);
print(arr,len);
int arr1[] = {3,9,5,1,6,2,8,4,0,7};
int len1 = sizeof(arr1)/sizeof(arr1[0]);
print(arr1,len1);
HeapSort(arr1,len1);
print(arr1,len1);
int arr2[] = {48,62,35,77,55,14,35,98};
int len2 = sizeof(arr2)/sizeof(arr2[0]);
print(arr2,len2);
HeapSort(arr2,len2);
print(arr2,len2);
return 0;
}
/*************************************************************************
> File Name: HeapSort.cpp
> Author: arrayli
> Mail: [email protected]
> Created Time: 2018年03月27日 星期二 14时33分47秒
************************************************************************/
// 直接插入排序:
// 时间复杂度: O(nlog2n)
// 最好: O(nlog2n)
// 最欢情况: O(nlog2n)
// 空间复杂度: O(1)
// 稳定性: 稳定
#include<stdio.h>
// 将堆顶元素与末尾元素进行交换
template<typename T>
void Swap( T* arr,int heapTop,int heapTail )
{
T temp = arr[heapTop];
arr[heapTop] = arr[heapTail];
arr[heapTail] = temp;
}
// 调整小根堆
template<typename T>
void AdjustHeap(T *arr,int currentNode,int HeapLength)
{
int leftChild = 0,rightChild = 0 ,min = 0;
leftChild = 2*currentNode + 1;
rightChild = 2*currentNode + 2;
// 判断 当前结点的左子节点是否大于当前结点,如果大于当前结点,则 largest = rightChild;
if(leftChild< HeapLength && arr[leftChild] < arr[currentNode])
min = leftChild;
// 否则 largest = currentNode;
else
min = currentNode;
// 然后判断当前结点的右子节点是否大于 largest
if(rightChild < HeapLength && arr[rightChild] < arr[min])
min = rightChild;
if(min != currentNode)
{
// 交换最大结点和当前结点的值
// 即将堆顶元素与末尾元素进行交换
Swap(arr,currentNode,min);
// 重新对堆进行调整
AdjustHeap(arr,min,HeapLength);
}
}
// 构建小根堆
template<typename T>
void MaxHeapCreat(T *arr,int len)
{
int i = 0;
for( i = len/2;i>=0; i-- )
{
AdjustHeap(arr,i,len);
}
}
// 小根堆排序
template<typename T>
void HeapSort(T *arr,int len)
{
// 构建小根堆
MaxHeapCreat(arr,len);
for(int i = len-1;i>=0;i--)
{
// 交换堆顶和最后一个元素,即每次将剩余元素中的最小者放到最后面
Swap(arr,0,i);
// 又一次调用堆顶点成为小根堆,仅仅有被交换的分支才有可能不是小根堆
AdjustHeap(arr,0,i);
}
}
template<typename T>
void print(T *arr,int len)
{
for(int i=0;i<len;i++)
{
printf("%d\t",arr[i]);
}
printf("\n");
}
int main(void)
{
int arr[] = {9,8,7,6,5,4,3,2,1,0};
int len = sizeof(arr)/sizeof(arr[0]);
print(arr,len);
HeapSort(arr,len);
print(arr,len);
int arr1[] = {3,9,5,1,6,2,8,4,0,7};
int len1 = sizeof(arr1)/sizeof(arr1[0]);
print(arr1,len1);
HeapSort(arr1,len1);
print(arr1,len1);
int arr2[] = {48,62,35,77,55,14,35,98};
int len2 = sizeof(arr2)/sizeof(arr2[0]);
print(arr2,len2);
HeapSort(arr2,len2);
print(arr2,len2);
return 0;
}
3、后缀表达式
前缀表达式、中缀表达式、后缀表达式都是四则运算的表达方式,用以四则运算表达式求值,即数学表达式的求值。
前缀表达式:前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前。比如:- × + 3 4 5 6。前缀表达式求值:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
中缀比表达式:中缀表达式就是常见的运算表达式,如(3+4)×5-6。
后缀表达式:后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后。比如: 3 4 + 5 × 6 - 。
具体使用方法,参考博客:https://www.cnblogs.com/Hslim/p/5008460.html
4、哈夫曼编码
参考博客:https://blog.csdn.net/dongfei2033/article/details/80657360
5、二叉树的结点计算问题及性质
性质1 : 二叉树的第 i 层上至多有 2^(i-1) 个结点 (i>=1)
性质2 : 深度为 k 的二叉树至多有 2^k -1 个结点( k>=1)
性质3 : 对任意的一颗二叉树 T ,若叶子结点数为 n0,而其度数为 2 的结点数为 n2,则 n0 = n2+1
性质4 : 具有 n 个结点的完全二叉树的深度 [log2n]+1
性质 5: 如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有
(1).如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2],向下取整
(2).如果2i>n那么节点i没有左孩子,否则其左孩子为2i
(3).如果2i+1>n那么节点没有右孩子,否则右孩子为2i+16、关系型数据库的构成
关系型数据是指以关系数学模型来表示的数据,关系数学模型中以二维表的形式来描述数据。关系型数据库是存储在计算机上的、可共享的、有组织的关系型数据的集合。 关系模型由关系数据结构,关系操作集合、关系完整性约束三部分组成。
7、文件逻辑记录和文件物理记录
记录是文件存取操作的基本单位。逻辑记录:是按用户观点的基本存取单位。物理记录:是按外存设备观点的基本存取单位。通常逻辑记录和物理记录之间存在三种关系:(1)一个物理记录存放一个逻辑记录; (2)一个物理记录包含多个逻辑记录; (3)多个物理记录表示一个逻辑记录。
8、sql 的索引,主键,唯一索引,联合索引的区别,对数据库有什么影响
(1)索引是一种特殊的文件,它们包含数据表里的所有记录的引用指针。索引的遵照原则:
(a). 最左侧原则:表的最左侧一列,往往数据不会发生改变,不影响其他列的数据
(b).命名短小原则:索引命名过长会使索引文件变大,损耗内存。
(2). 普通索引(由关键字 KEY或 INDEX 定义得到的索引):加快数据的查询速度
(3). 唯一索引(由关键字 UNIQUE 把它定义为唯一索引):保证数据的唯一性
(4). 主键:一种特殊的唯一索引,一张表中只能定义一个主键索引,用来标识唯一一条数据,用 PRIMARY KEY 创建
(5). 联合索引:索引可以覆盖多个数据列,如像 INDEX 索引就是联合索引
索引可以极大的提高查询访问速度,但是会降低插入,删除,更新表的速度,应为在执行写的操作的时候还要操作索引文件。
9、TCP 传输的时候怎么保证传输的可靠性
参考我的往期博客:
https://blog.csdn.net/qq_35396127/article/details/80847189
10、在数组中找出三个数字使得它们的和为0,找出所有的这种不包含重复的组合。
set<vector<int>> find_triplets(vector<int> arr)
{
sort(arr.begin(), arr.end());
set<vector<int>>ret;
vector<int>temp(3);
int n = arr.size();
for (int i = 0; i < n; ++i)
{
int j = i + 1;
int k = n - 1;
while (j < k)
{
int sum_two = arr[i] + arr[j];
if (sum_two + arr[k] < 0)
++j;
else if (sum_two + arr[k] > 0)
--k;
else
{
temp[0] = arr[i];
temp[1] = arr[j];
temp[2] = arr[k];
ret.insert(temp);
++j;
--k;
}
}
}
return ret;
}