浙江大学MOOC数据结构-陈越、何钦铭 编程练习题(第九讲)

浙江大学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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值