浙江大学MOOC数据结构-陈越、何钦铭 编程练习题(第九讲)
编程说明
编程环境:平台运行
编程语言:C
第一题代码
#include <stdio.h>
#include <stdlib.h>
//#include <windows.h>
void DataGet(void);//数据获取
void DataPrint(void);//数据打印
void Swap(int *x, int *y);//数值交换
void Bubble_Sort(int A[], int N);//冒泡排序
void Insert_Sort(int A[], int N);//插入排序
void Shell_Sort(int A[], int N);//希尔排序
void Selection_Sort(int A[], int N);//选择排序
void Heap1_Sort(int A[], int N);//堆排序1
void Heap2_Sort(int A[], int N);//堆排序2
void BuildHeap(int A[], int N);//建立最小堆
void PercDown(int A[], int i, int N);//过滤
int DeleteMin(int n);//取出堆顶元素
void Merge_Sort_R(int A[], int N);//递归型归并排序
void MSort(int A[], int TmpA[], int L, int R);//排序
void Merge(int A[], int TmpA[], int L, int R, int RightEnd);//合并
void Merge_Sort(int A[], int N);//非递归型归并排序
void Merge_Pass(int A[], int TmpA[], int N, int length);
void QuickSort(int A[], int N);//快速排序封装函数
void Qsort(int A[], int L, int R);//快速排序
int Median3(int A[], int L, int R);//左中右取中值
int N, A[100000];
int main(void)
{
DataGet();
//Bubble_Sort(A, N);
//Insert_Sort(A, N);
//Shell_Sort(A, N);
//Selection_Sort(A, N);
//Heap1_Sort(A, N);
//Heap2_Sort(A, N);
//Merge_Sort_R(A, N);
//Merge_Sort(A, N);
QuickSort(A, N);
DataPrint();
// system("pause");
return 0;
}
void DataGet(void)
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
}
void DataPrint(void)
{
int flag = 0;
for (int i = 0; i < N; i++)
{
if (!flag)
{
flag = 1;
printf("%d", A[i]);
}
else
printf(" %d", A[i]);
}
}
void Swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void Bubble_Sort(int A[], int N)
{
int flag;
for (int i = 1; i < N; i++)//N-1趟
{
flag = 0;
for (int j = 0; j < N - i; j++)//前N-i个元素进行排序
{
if (A[j] > A[j + 1])
{
flag = 1;
Swap(&A[j], &A[j + 1]);
}
}
if (!flag)
break;
}
}
void Insert_Sort(int A[], int N)
{
int Temp;
int i, j;
for (i = 1; i < N; i++)//摸N-1张新牌
{
Temp = A[i];//新牌存放于临时变量
for (j = i; j >= 1 && A[j - 1] > Temp; j--) //寻找比新牌大的旧牌
{
A[j] = A[j - 1];//旧的大牌依次后移
}
A[j] = Temp;//新牌插入
}
}
//插入排序是保留第一张牌A[0],后面的牌依次摸入插入
//希尔排序是保留前间隔数目张牌A[0]……A[D],后面的牌依次摸入间隔D插入
void Shell_Sort(int A[], int N)
{
int i, j;
int Tmp;
for (int D = N / 2; D > 0; D /= 2)
{
for (i = D; i < N ; i++)//N-D次摸牌
{
Tmp = A[i];// 新牌存放临时变量
for (j = i; j >= D && A[j - D] > Tmp; j -= D)//新牌与旧牌比较
{
A[j] = A[j - D];//大牌后移
}
A[j] = Tmp;//新牌插入
}
}
}
void Selection_Sort(int A[], int N)
{
for (int i = 0; i < N - 1; i++)
{
int min = i;
for (int j = i + 1; j < N; j++)
{
if (A[j] < A[min])
min = j;
}
Swap(&A[i], &A[min]);
}
}
void Heap1_Sort(int A[], int N)
{
int Tmp[100000];
BuildHeap(A, N);
for (int i = 0; i < N; i++)
{
Tmp[i] = DeleteMin(i);
}
for (int i = 0; i < N; i++)
{
A[i] = Tmp[i];
}
}
void Heap2_Sort(int A[], int N)
{
BuildHeap(A, N);
for (int i = 0; i < N - 1; i++)
{
Swap(&A[0], &A[N - 1 - i]);
PercDown(A, 0, N - 1 - i);
}
//如果建立的是最大堆,就不用单独打印了
int flag = 0;
for (int i = N-1; i >= 0; i--)
{
if (!flag)
{
flag = 1;
printf("%d", A[i]);
}
else
printf(" %d", A[i]);
}
}
void BuildHeap(int A[], int N)
{
//从第一个父节点开始依次过滤
for (int i = N / 2 - 1; i >= 0; i--)
{
PercDown(A, i, N);
}
}
void PercDown(int A[], int i, int N)
{
int Parent, Child;
int Tmp = A[i];//父亲节点数据存放给临时变量
for (Parent = i; Parent * 2 + 1 < N;Parent = Child)//向下过滤
{
Child = Parent * 2 + 1;
if (((Child + 1) != N ) && A[Child + 1] < A[Child])//存在右孩子,选择左右孩子较小的
{
Child++;
}
if (A[Child] < Tmp)
A[Parent] = A[Child];
else
break;
}
A[Parent] = Tmp;//找到位置
}
int DeleteMin(int n)
{
int Item = A[0];//堆顶最小值
A[0] = A[N - 1 - n];//末尾元素付给临时变量用于向下过滤
int Num = N - 1 - n;
PercDown(A, 0, Num);
return Item;
}
void Merge_Sort_R(int A[], int N)
{
int *TmpA;
TmpA =(int *) malloc(N * sizeof(int));
if (TmpA != NULL)
{
MSort(A, TmpA, 0, N - 1);
free(TmpA);
}
else
printf("Error: Lack Of Space");
}
void MSort(int A[], int TmpA[], int L, int RightEnd)
{
int Center;
if (L < RightEnd)
{
Center = (L + RightEnd) / 2;//分而治之
MSort(A, TmpA, L, Center); //左半
MSort(A, TmpA, Center + 1, RightEnd); //右半
Merge(A, TmpA, L, Center + 1, RightEnd);//合并
}
}
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置 */
void Merge(int A[], int TmpA[], int L, int R, int RightEnd)
{
int LeftEnd = R - 1;/* 左边终点位置。假设左右两列挨着 */
int Tmp = L; /* 存放结果的数组的初始位置 */
int NumElements = RightEnd - L + 1;
while (L <= LeftEnd && R <= RightEnd)
{
if (A[L] <= A[R])
TmpA[Tmp++] = A[L++];
else
TmpA[Tmp++] = A[R++];
}
while (L <= LeftEnd) /* 直接复制左边剩下的 */
{
TmpA[Tmp++] = A[L++];
}
while (R <= RightEnd) /*直接复制右边剩下的 */
{
TmpA[Tmp++] = A[R++];
}
for (int i = 0; i < NumElements; i++, RightEnd--)
{
A[RightEnd] = TmpA[RightEnd];
}
}
void Merge_Sort(int A[], int N)
{
int *TmpA;
int length = 1;
TmpA = (int *)malloc(N * sizeof(int));
if (TmpA != NULL)
{
while (length < N)
{
Merge_Pass(A, TmpA, N, length);
length *= 2;
Merge_Pass(TmpA, A, N, length);
length *= 2;
}
free(TmpA);
}
else
printf("Error: Lack Of Space");
}
void Merge_Pass(int A[], int TmpA[], int N, int length) /* length = 当前有序子列的长度 */
{
int i;
for (i = 0; i <= N - 2 * length; i += 2 * length)
{
Merge(A, TmpA, i, i + length, i + 2 * length - 1);
}
if (i + length < N)/* 归并最后2个子列 */
{
Merge(A, TmpA, i, i + length, N - 1);
}
else/* 最后只剩1个子列 */
{
for (int j = i; j < N; j++)
{
TmpA[j] = A[j];
}
}
}
void QuickSort(int A[], int N)
{
Qsort(A, 0, N - 1);
}
int Cutoff = 0;//小规模数据阈值
void Qsort(int A[], int L, int R)
{
if (Cutoff < L - R)
{
int Pivot = Median3(A, L, R);
int i = L, j = R - 1;
while (1)
{
while (A[++i] > Pivot);
while (A[--j] < Pivot);
if (i < j)
Swap(&A[i], &A[j]);
else
break;
}
Qsort(A, L, i - 1);
Qsort(A, i + 1, R);
}
else
Insert_Sort(A + L, R - L + 1);
}
int Median3(int A[], int L, int R)
{
int Center = (L + R) / 2;
if (A[L] > A[Center])
{
Swap(&A[L], &A[Center]);
}
if (A[L] > A[R])
{
Swap(&A[L], &A[R]);
}
if (A[Center] > A[R])
{
Swap(&A[Center], &A[R]);
}
/* A[ Left ] <= A[ Center ] <= A[ Right ] */
Swap(&A[Center], &A[R - 1]);/* 将pivot藏到右边 */
/* 只需要考虑 A[ Left+1 ] … A[ Right–2 ] */
return A[R - 1]; /* 返回 pivot */
}
基数排序
注:仅是为了自己熟悉代码而写,没有在平台运行,毕竟平台数据有负数。
Visual Studio 2015
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define MaxDigit 4
#define Radix 10
//桶元素节点
typedef struct Node *PtrToNode;
struct Node
{
int key;
PtrToNode next;
};
//桶元素头节点
typedef struct HeadNode Bucket[Radix];
struct HeadNode
{
PtrToNode head, tail;
};
void DataGet(void);//数据获取
void DataPrint(void);//数据打印
int GetDigit(int X, int D);//获取数字的基数
void LSDRadixSort(int A[], int N);//低位优先基数排序
void MSD(int A[], int L, int R, int D);//主位优先基数排序
void MSDRadixSort(int A[], int N);//主位优先基数排序封装函数
int N, A[100000];
int main(void)
{
DataGet();
MSDRadixSort(A, N);
//LSDRadixSort(A, N);
DataPrint();
system("pause");
return 0;
}
int GetDigit(int X, int D)
{
/* 默认次位D=1, 主位D<=MaxDigit */
int base;
for (int i = 1; i <= D; i++)
{
base = X % Radix;
X = X / Radix;
}
return base;
}
void DataGet(void)
{
scanf_s("%d", &N);
for (int i = 0; i < N; i++)
{
scanf_s("%d", &A[i]);
}
}
void DataPrint(void)
{
int flag = 0;
for (int i = 0; i < N; i++)
{
if (!flag)
{
flag = 1;
printf("%d", A[i]);
}
else
printf(" %d", A[i]);
}
}
//List是链表,P可以看成是链表的别称,Tmp是链表里面独立的单个节点
void LSDRadixSort(int A[], int N)
{
/* 基数排序 - 次位优先 */
int Di;
Bucket B;
PtrToNode Tmp, P, List = NULL;
//初始化每个桶为空链表
for (int i = 0; i < Radix; i++)
{
B[i].head = NULL;
B[i].tail = NULL;
}
/* 将原始序列逆序存入初始链表List */
for (int i = 0; i < N; i++)
{
Tmp = (PtrToNode)malloc(sizeof(struct Node));//Tmp指向新创建的节点
Tmp->key = A[i];//新节点数值更新
Tmp->next = List;//新节点接在原链表上首部
List = Tmp;//List记录当前链表的首部
}
//下面开始排序
for (int i = 1; i <= MaxDigit; i++)/* 对数据的每一位循环处理 */
{
//下面是分配的过程
//P指向链表首部
P = List;
while (P)
{
Di = GetDigit(P->key, i);/* 获得当前元素的当前位数字 */
Tmp = P;
P = P->next;/* 从List中摘除 */
//注:一定要先把P后移才能再对Tmp进行NULL
Tmp->next = NULL;/* 插入B[Di]号桶尾 */
if (B[Di].head == NULL)//空桶
{
B[Di].head = Tmp;
B[Di].tail = Tmp;
}
else//非空桶
{
B[Di].tail->next = Tmp;
B[Di].tail = Tmp;
}
}
//下面是收集的过程
List = NULL;
for (int i = Radix - 1; i >= 0; i--)/* 将每个桶的元素顺序收集入List */
{
if (B[i].head)/* 如果桶不为空 */
{
//整桶插入List表头
B[i].tail->next = List;
List = B[i].head;
//桶清空
B[i].head = NULL;
B[i].tail = NULL;
}
}
}
/* 将List倒入A[]并释放空间 */
for (int i = 0; i < N; i++)
{
Tmp = List;
List = List->next;
A[i] = Tmp->key;
free(Tmp);
}
}
void MSD(int A[], int L, int R, int D)
{ /* 核心递归函数: 对A[L]...A[R]的第D位数进行排序 */
int Di;
int i, j;
Bucket B;
PtrToNode Tmp, P, List = NULL;
/* 递归终止条件 */
if (D == 0) return;
/* 初始化每个桶为空链表 */
for (int i = 0; i < Radix; i++)
{
B[i].head = NULL;
B[i].tail = NULL;
}
/* 将原始序列逆序存入初始链表List */
for (int i = L; i <= R; i++)
{
Tmp = (PtrToNode)malloc(sizeof(struct Node));
Tmp->key = A[i];
Tmp->next = List;
List = Tmp;//链表头前移
}
/* 下面是分配的过程 */
P = List;
while (P)
{
Di = GetDigit(P->key, D);/* 获得当前元素的当前位数字 */
/* 从List中摘除 */
Tmp = P;
P = P->next;
Tmp->next = NULL;
/* 插入B[Di]号桶 */
if (B[Di].head == NULL)
{
B[Di].head = Tmp;
B[Di].tail = Tmp;
}
else
{
B[Di].tail->next = Tmp;
B[Di].tail = Tmp;
}
}
/* 下面是收集的过程 */
i = j = L; /* i, j记录当前要处理的A[]的左右端下标 */
for (int Di = 0; Di < Radix; Di++)/* 对于每个桶 */
{
if (B[Di].head)/* 将非空的桶整桶倒入A[], 递归排序 */
{
P = B[Di].head;
while (P)
{
Tmp = P;
P = P->next;
A[j++] = Tmp->key;
free(Tmp);
}
/* 递归对该桶数据排序, 位数减1 */
MSD(A, i, j - 1, D - 1);
i = j;/* 为下一个桶对应的A[]左端 */
}
}
}
void MSDRadixSort(int A[], int N)
{
MSD(A, 0, N - 1, MaxDigit);
}
第二题代码
/*
思路:
·扫描第二个数组B[],找到递减的Index下标
·第二个数组B[]和第一个数组A[]针对Index下标及其之后的元素进行比对,比对一致,说明是插入排序,否则是归并排序
·如果是插入排序,从Index下标开始在进行一次插入排序,输出结果
·如果是归并排序,则需要2 4 6 8的length去测试,看哪个长度的数组排序不对,则说明此length有错误,直接对此length进行一次归并就好
*/
#include <stdio.h>
#include <stdlib.h>
//#include <windows.h>
void DataGet(void);//数据获取
void DataPrint(void);//数据打印
int Judge(int B[], int N);//判断插入排序或者归并排序函数
int JudgeLength(int B[], int L, int R);//判断归并排序的length
void Merge_pass(int A[], int TmpA[], int N, int length);
void Merge(int A[], int TmpA[], int L, int R, int RightEnd);
void Insert_Sort_Part(int A[], int N);//进行一次插入
void MergeSort(int A[],int N);//判断归并length并进行一次迭代
int N, A[100], B[100];//N数组元素数目、A[]初始数组、B[]部分排序后的数组
int flag = 0;//插入排序(1) or 归并排序(2)的标志位
int Index;//数组逆序位置下标
int main(void)
{
DataGet();//数据获取
Index = Judge(B, N);//判断插入排序或者归并排序函数
if (flag == 1)//插入排序
{
Insert_Sort_Part(B, N);//再进行一次迭代插入排序
}
else if (flag == 2)//归并排序
{
MergeSort(B, N);
}
DataPrint();//数据打印
// system("pause");
return 0;
}
void DataGet(void)
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
}
void DataPrint(void)
{
int flag = 0;
for (int i = 0; i < N; i++)
{
if (!flag)
{
flag = 1;
printf("%d", B[i]);
}
else
printf(" %d", B[i]);
}
}
void Swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int Judge(int B[], int N)
{
int Index;
int i;
//寻找跳变点Index
for (i = 0; i < N; i++)
{
if (B[i - 1] > B[i])
{
Index = i;
break;
}
}
//A[]和B[]对Index及其之后的数组进行比对
//比对一致,说明插入排序,否则为归并排序
for (i = Index; i < N; i++)
{
if (A[i] == B[i])
continue;
else
break;
}
if (i == N)
{
flag = 1;
printf("Insertion Sort\n");
}
else
{
flag = 2;
printf("Merge Sort\n");
}
return Index;
}
//判断归并排序的length
int JudgeLength(int B[], int L, int R)
{
int i;
for (i = L; i < R; i++)
{
if (B[i] <= B[i + 1])
continue;
else
break;
}
if (i == R)
return 1;
else
return 0;
}
void Merge_pass(int A[], int TmpA[], int N, int length)/* length = 当前有序子列的长度 */
{
int i;
for (i = 0; i <= N - 2 * length; i += 2*length)
{
Merge(A, TmpA, i, i+length, i+2*length-1);
}
if (i + length < N)/* 归并最后2个子列 */
{
Merge(A, TmpA, i, i+length, N - 1);
}
else/* 最后只剩1个子列 */
{
for (int j = i; j < N; j++)
{
TmpA[j] = A[j];
}
}
for (int i = 0; i < N; i++)
{
A[i] = TmpA[i];
}
}
/* L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置 */
void Merge(int A[], int TmpA[], int L, int R, int RightEnd)
{
int LeftEnd = R - 1; /* 左边终点位置。假设左右两列挨着 */
int Tmp = L;/* 存放结果的数组的初始位置 */
while (L <= LeftEnd && R <= RightEnd)
{
if (A[L] <= A[R])
TmpA[Tmp++] = A[L++];
else
TmpA[Tmp++] = A[R++];
}
while (L <= LeftEnd)/* 直接复制左边剩下的 */
{
TmpA[Tmp++] = A[L++];
}
while (R <= RightEnd)/*直接复制右边剩下的 */
{
TmpA[Tmp++] = A[R++];
}
}
void Insert_Sort_Part(int B[], int N)
{
int j;
int Tmp = B[Index];//摸牌
for (j = Index; j >= 1 && B[j - 1] > Tmp; j--)//模的牌与前面牌进行比较
{
B[j] = B[j - 1];
}
B[j] = Tmp;//插入新牌
}
void MergeSort(int A[], int N)
{
int length = 2;
int Value = -1;
int *TmpB = (int *)malloc(N * sizeof(int));
if (TmpB != NULL)
{
for (; length < N; length *= 2)
{
for (int i = 0; i < N; i += length)
{
if (i + length - 1 < N)
Value = JudgeLength(B, i, i + length - 1);
else
Value = JudgeLength(B, i, N - 1);
if (Value == 0)
break;
}
if (Value == 0)
break;
}
length = length / 2;
Merge_pass(B, TmpB, N, length);
}
else
printf("Error: Lack Of Space");
}
C++做法
借鉴自https://blog.youkuaiyun.com/qq_32511479/article/details/59117368
/*
·思路:模拟插入排序过程,每插入一次与所给排序序列进行比对,比对一致则为插入排序,再进行一次迭代
· 比对不一致,则模拟归并排序,进行比对,比对成功,则为归并排序,再进行一次迭代
*/
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
//#include <windows.h>
using namespace std;
void DataGet(void);//数据获取
void DataPrint(int B[]);//数据打印
bool JudgeInsert(int A[], int B[], int N);//插入排序模拟比对函数
bool JudgeMerge(int A[], int B[], int N);//归并排序模拟比对函数
int N, A[100], CopyA[100], B[100];//N数组元素数目、A[]初始数组、CopyA[]拷贝数组、排序数组B[]
int main(void)
{
int Flag;
DataGet();//数据获取
Flag=JudgeInsert(CopyA, B, N);
if (!Flag)
JudgeMerge(A, B, N);
// system("pause");
return 0;
}
void DataGet(void)
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
CopyA[i] = A[i];
}
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
}
void DataPrint(int B[])
{
int flag = 0;
for (int i = 0; i < N; i++)
{
if (!flag)
{
flag = 1;
printf("%d", B[i]);
}
else
printf(" %d", B[i]);
}
}
bool IsSame(int A[], int B[], int N)
{
for (int i = 0; i < N; i++)
{
if (A[i] != B[i])
return false;
}
return true;
}
bool JudgeInsert(int A[], int B[], int N)
{
bool Mark = false;
int Tmp;
int j;
for (int i = 1; i < N; i++)
{
//比对
if (i != 1 && IsSame(A, B, N))//初始序列不比较
{
Mark = true;
}
//插排
Tmp = A[i];
for (j = i; j >= 1 && A[j - 1] > Tmp; j--)
{
A[j] = A[j - 1];
}
A[j] = Tmp;
if (Mark)
{
break;
}
}
//处理
if (Mark)
{
printf("Insertion Sort\n");
DataPrint(A);
}
return Mark;
}
bool JudgeMerge(int A[], int B[], int N)
{
bool Mark=false;
for (int length = 2; length/2 <= N; length *= 2)
{
//比对
if (length != 2 && IsSame(A, B, N))//初始序列不比较
{
Mark = true;
}
//排序
for (int j = 0; j < N; j += length)
{
sort(A + j, A + min(j + length, N));
}
if (Mark)
{
printf("Merge Sort\n");
DataPrint(A);
return Mark;
}
}
return Mark;
}
第三题代码
C++
/*
·思路:模拟插入排序过程,每插入一次与所给排序序列进行比对,比对一致则为插入排序,再进行一次迭代
· 比对不一致,则模拟归并排序,进行比对,比对成功,则为归并排序,再进行一次迭代
*/
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
//#include <windows.h>
using namespace std;
void DataGet(void);//数据获取
void DataPrint(int B[]);//数据打印
void Swap(int *x, int *y);//数据交换
bool JudgeInsert(int A[], int B[], int N);//插入排序模拟比对函数
bool JudgeHeap(int A[], int B[], int N);//归并排序模拟比对函数
void BuildHeap(int A[], int N);//建立最大堆
void PercDown(int A[], int Parent, int N);//堆的过滤
int N, A[100], CopyA[100], B[100];//N数组元素数目、A[]初始数组、CopyA[]拷贝数组、排序数组B[]
int main(void)
{
int Flag;
DataGet();//数据获取
Flag = JudgeInsert(CopyA, B, N);
if (!Flag)
JudgeHeap(A, B, N);
// system("pause");
return 0;
}
void DataGet(void)
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
CopyA[i] = A[i];
}
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
}
void DataPrint(int B[])
{
int flag = 0;
for (int i = 0; i < N; i++)
{
if (!flag)
{
flag = 1;
printf("%d", B[i]);
}
else
printf(" %d", B[i]);
}
}
bool IsSame(int A[], int B[], int N)
{
for (int i = 0; i < N; i++)
{
if (A[i] != B[i])
return false;
}
return true;
}
void Swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
bool JudgeInsert(int A[], int B[], int N)
{
bool Mark = false;
int Tmp;
int j;
for (int i = 1; i < N; i++)
{
//比对
if (i != 1 && IsSame(A, B, N))//初始序列不比较
{
Mark = true;
}
//插排
Tmp = A[i];
for (j = i; j >= 1 && A[j - 1] > Tmp; j--)
{
A[j] = A[j - 1];
}
A[j] = Tmp;
if (Mark)
{
break;
}
}
//处理
if (Mark)
{
printf("Insertion Sort\n");
DataPrint(A);
}
return Mark;
}
bool JudgeHeap(int A[], int B[], int N)
{
bool Mark = false;
BuildHeap(A, N);
for (int i = 1; i < N; i++)
{
//比对
if (i != 1 && IsSame(A, B, N))//初始序列不比较
{
Mark = true;
}
//把最大元素放入末尾,然后剩下的元素进行堆排序
Swap(&A[0], &A[N - i]);
PercDown(A, 0, N - i);
if (Mark)
{
printf("Heap Sort\n");
DataPrint(A);
break;
}
}
return Mark;
}
void BuildHeap(int A[], int N)
{
for (int i = N / 2 - 1; i >= 0; i--)
{
PercDown(A, i, N);
}
}
void PercDown(int A[], int Parent, int N)
{
int Tmp = A[Parent];//父节点
int Child = Parent * 2 + 1;
for ( ; Parent * 2 + 1 < N; Parent = Child)//存在儿子节点
{
Child = Parent * 2 + 1;//左儿子节点
if ((Child + 1) < N && A[Child] < A[Child + 1])//存在右节点,右节点大于左节点
{
Child++;//指向右节点
}
if (A[Child] > Tmp)//儿子节点大于父节点,则儿子节点应覆盖父节点,父节点到儿子节点位置继续过滤
{
A[Parent] = A[Child];
}
else
break;
}
A[Parent] = Tmp;
}