堆排序和简单选择排序

简单选择排序就是每次从i到N-1中选择最小的数,然后放在第i个位置,其算法复杂度为O(N2);
堆排序是简单选择排序的改进,通过建立最大堆,每次将最大堆的根节点取出放在最后的位置,然后再重新调整为最大堆,时间复杂度为O(NlogN)。

  1. 简单排序算法
void Select_Sort(SqList *L)
/*简单选择排序,算法复杂度为O(N2),不稳定*/
{
	int postion;
	for (int i = 0; i < L->Length; i++)
	{
		postion = ScanfForMin(*L, i, L->Length - 1);//每次从i到N-1中找到最小的元素的位置
		Swap(&L->data[postion], &L->data[i]);
	}

}

2.堆排序算法

void Heap_Sort(SqList *L)
/*堆排序*/
{
	BuildMaxHeap(L);//建立最大堆
	for (int i = L->Length - 1; i >= 0; i--)
	{
		Swap(&L->data[0], &L->data[i]);//把最大的第一个结点和最后一个交换位置
		PercDown(L, 0, i-1);//向下调整
	}
}

堆排序算法最核心的部分是建立最大堆和最大堆的调整,调整方法为向下过滤法。
向下过滤算法:在一棵子树中,对于根结点parent,如果parent的元素值比child中最大的元素要小则交换parent和child的位置。然后令parent=child,继续比较。这样这棵子树为最大堆。

void PercDown(SqList *L, int root, int end)
{/*向下过滤*/
	int child, parent;
	parent = root;
	for (parent = root; (parent*2+1)<end; parent=child) // parent有孩子
	{
		child = parent * 2 + 1;//左孩子
		if ((child + 1) <= end && L->data[child] < L->data[child + 1]) //从左右孩子中找到最大的孩子
			child++;
		if (L->data[parent] < L->data[child])//如果孩子比父亲大就交换位置
			Swap(&L->data[parent], &L->data[child]);
		else//如果parent比child大则退出循环
			break;
	}
}

建立最大堆
我们选择从下到上一步步建立最大堆,逐步向下调整。

void BuildMaxHeap(SqList *L)
/*建立最大堆*/
{
	if (L->Length % 2 == 0)//末结点下标为奇数
	{
		for (int i = (L->Length - 1) / 2; i >= 0; i--)
		{
			PercDown(L, i, L->Length - 1);
		}
	}
	else//末结点下标为偶数
	{
		for (int i = (L->Length - 2) / 2; i >= 0; i--)
		{
			PercDown(L, i, L->Length - 1);
		}
	}
}

完整的测试代码

// Selection_Sort.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100


typedef int ElementType;
typedef struct
{
	ElementType data[MaxSize];
	int Length;
}SqList;

void Swap(ElementType *a, ElementType *b)
{
	ElementType tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}


void DisplaySqList(SqList L)
/*打印序列*/
{
	int i;
	for (i = 0; i < L.Length; i++)
	{
		printf("%-4d", L.data[i]);
	}
	printf("\n");
}


int ScanfForMin(SqList L, int Left, int Right)
/*在序列中找出最小的元素所在的位置*/
{
	int pos=Left;
	ElementType tmp;
	for (int i = Left; i <= Right; i++)
	{
		tmp = L.data[pos];
		if (tmp > L.data[i])
			pos = i;
	}
	return pos;
}


void Select_Sort(SqList *L)
/*简单选择排序,算法复杂度为O(N2),不稳定*/
{
	int postion;
	for (int i = 0; i < L->Length; i++)
	{
		postion = ScanfForMin(*L, i, L->Length - 1);//每次从i到N-1中找到最小的元素的位置
		Swap(&L->data[postion], &L->data[i]);
	}

}

void PercDown(SqList *L, int root, int end)
{/*向下过滤*/
	int child, parent;
	parent = root;
	for (parent = root; (parent*2+1)<end; parent=child) // parent有孩子
	{
		child = parent * 2 + 1;//左孩子
		if ((child + 1) <= end && L->data[child] < L->data[child + 1]) //从左右孩子中找到最大的孩子
			child++;
		if (L->data[parent] < L->data[child])//如果孩子比父亲大就交换位置
			Swap(&L->data[parent], &L->data[child]);
		else//如果parent比child大则退出循环
			break;
	}
}


void BuildMaxHeap(SqList *L)
/*建立最大堆*/
{
	if (L->Length % 2 == 0)//末结点下标为奇数
	{
		for (int i = (L->Length - 1) / 2; i >= 0; i--)
		{
			PercDown(L, i, L->Length - 1);
		}
	}
	else//末结点下标为偶数
	{
		for (int i = (L->Length - 2) / 2; i >= 0; i--)
		{
			PercDown(L, i, L->Length - 1);
		}
	}
}

void Heap_Sort(SqList *L)
/*堆排序*/
{
	BuildMaxHeap(L);//建立最大堆
	for (int i = L->Length - 1; i >= 0; i--)
	{
		Swap(&L->data[0], &L->data[i]);//把最大的第一个结点和最后一个交换位置
		PercDown(L, 0, i-1);//向下调整
	}
}

 

int main()
{

	SqList L, L1;
	ElementType A[] = { 1,34,23,45,2,4,66,32,65,46,31,44 };
	int len = sizeof(A) / sizeof(A[0]);
	for (int i = 0; i < len; i++)
	{
		L.data[i] = A[i];
	}
	L.Length = len;
	L1 = L;
	printf("排序前:\n");
	DisplaySqList(L);
	printf("简单选择排序:\n");
	Select_Sort(&L);
	DisplaySqList(L);
	printf("堆排序:\n");
	Heap_Sort(&L1);
	DisplaySqList(L1);


    
}



程序运行截图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38904904/article/details/89878883
今日推荐