归并排序和堆排序的关键字比较次数和记录的移动次数怎么找呀
```c++
//堆排序
// 只是找到当前数据节点的位置(让当前根节点都比自己的两个孩子大)
void heap_siftdown(int a[],int n,int p) { //调整算法
int i = p,j = i*2+1; //j是i的左子节点
int tmp = a[i]; //tmp是临时变量
while(j < n) //适用于多层树
{
if(j+1 < n && a[j] < a[j+1])
j++;
if(a[j] <= tmp) //如果当前根比两个孩子都大了,则break,tmp是虚拟的当前节点
break;
else
{
a[i] = a[j]; //将大孩子给当前根
i = j;j = j*2+1;
}
}
a[i] = tmp;
}
void HeapSort(int a[],int n)
{
int i;
for(i = (n-1)/2; i >= 0;i--) //(n-1)/2最右边有子孩子那个节点
heap_siftdown(a, n, i);
for(i = n;i >= 0; i--) //每一次将最大的换到末尾,再重排前面的剩下的
{
swap(a[i], a[0]);
heap_siftdown(a, i, 0); //自顶向下重排
}
}
//归并排序
void Merge(int *arr, int n){
int temp[n]; // 辅助数组
int b = 0; // 辅助数组的起始位置
int mid = n / 2; // mid将数组从中间划分,前一半有序,后一半有序
int first = 0, second = mid; // 两个有序序列的起始位置
while (first < mid && second < n){
if (arr[first] <= arr[second]){ // 比较两个序列
temp[b++] = arr[first++];
}
else{
temp[b++] = arr[second++];
}
}
while(first < mid){ // 将剩余子序列复制到辅助序列中
temp[b++] = arr[first++];
}
while(second < n){
temp[b++] = arr[second++];
}
for (int i = 0; i < n; i++){ // 辅助序列复制到原序列
arr[i] = temp[i];
}
}
void MergeSort(int *arr, int n){
if (n <= 1) // 递归出口
return;
if (n > 1){
MergeSort(arr, n / 2); // 对前半部分进行归并排序
MergeSort(arr + n / 2, n - n / 2); // 对后半部分进行归并排序
Merge(arr, n); // 归并两部分
}
}
```