PAT打卡第11天 1098. Insertion or Heap Sort (25)

// heap sort函数和down adjust函数 需要多多练习

/*
    题目总结:
    本题主要考插入排序和堆排序,其中堆排序是难点
    1)插入排序:插入排序比较简单,每次从原始序列中选未排序的第一个元素,加入到一个vector容器中
        用sort函数进行排序,这里需要注意的是,sort是对容器元素排序,一开始用的数组不行
        这里insertion写的比较乱,下次先想好思路,在动手写
    2)堆排序:一般分为大根堆和小根堆,这里是大根堆 
        需要注意的是,这里的数组元素要从下标1开始,才能满足相关的性质,如节点i的左孩子是2*i
        1.heap sort函数:
            首先需要建堆,for循环n/2次,调用down adjust函数 从后往前调整非终端节点 number/2 即最后一个非终端节点,初始i即为number/2
        2.down adjust(int low,int high)函数:
            i=low,j=2*i;j存储的是i的左孩子下标,i是树根,
            while(i有孩子节点,即j<=high)
                然后,比较孩子节点,如果j+1下标元素的值更大,让j=j+1;
                比较父节点i和孩子节点j的值那个更大,
                如果j的大,swap两个元素,然后令i=j,j=2*1 继续循环
                如果j更小,说明该节点已经无需继续下坠,退出循环
*/
 

#pragma warning(disable:4996)
#include<vector>
#include<iostream>
#include<algorithm>

using namespace std;

int heap[100];
int number;
int ini_seq[100];
int mid_seq[100];
vector<int> insert;

bool isSame(int A[], int B[]) {
	for (int i = 1; i < number+1; i++) {
		if (A[i] != B[i])return false;
	}
	return true;
}

bool insertion() {
	for (int i = 0; i < number; i++) {
		insert.push_back(ini_seq[i]);
	}
	bool flag = false;
	for (int i = 1; i < number; i++) {
		sort(insert.begin(), insert.begin()+i+1);
		for (int j = 0; j < number; j++) {
			if (insert[j] == mid_seq[j]) {
				if (j == number - 1) {
					if (i != number - 1) {
						sort(insert.begin(), insert.begin()+i+2);
					}
					return true;
				}
			}
			else {
				flag = false;
				break;
			};
		}
		if (i == number - 1) {
			return false;
		}
	}
}

void down_adjust(int low, int high) {
	int i = low, j = i * 2;
	// 存在孩子结点
	while (j <= high) {
		// 选取孩子节点中最大的节点
		if (j + 1 <= high && heap[j + 1] > heap[j]) {
			j = j + 1; // j存储右孩子结点
		}
		// 孩子结点中最大值大于父亲节点值 进行调整
		if (heap[j] > heap[i]) {
			swap(heap[i], heap[j]);
			i = j;
			j = i * 2;
		}
		// 若此时父亲节点值更大 调整结束
		else break;
	}
}

bool heap_sort() {
	int heap_ini[101];
	// 误区,注意堆序列是从1开始的 才满足相关性质
	for (int i = 0; i < number; i++) {
		heap[i+1]=ini_seq[i];
		heap_ini[i + 1] = mid_seq[i];
	}
	bool flag = false;
	// 从后往前调整非终端节点 number/2 即最后一个非终端节点
	for (int i = number / 2; i > 0; i--) {
		down_adjust(i, number); //建堆
	}
	for (int i = number; i > 1; i--) {
		// 比较heap数组和ini_seq数组
		if (i != number && isSame(heap, heap_ini)) {
			flag = true;
		}
		// 堆顶堆底元素互换
		swap(heap[1], heap[i]);
		down_adjust(1, i - 1);
		if (flag) {
			return true;
		}
	}
}

int main() {
	cin >> number;
	for (int i = 0; i < number; i++) {
		cin >> ini_seq[i];
	}
	for (int i = 0; i < number; i++) {
		cin >> mid_seq[i];
	}
	if (insertion()) {
		printf("Insertion Sort\n");
		for (int i = 0; i < number; i++) {
			printf("%d ", insert[i]);
		}
	}
	else {
		heap_sort();
		printf("Heap Sort\n");	
		for (int i = 1; i < number+1; i++) {
			printf("%d ", heap[i]);
		}
	}
	
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值