博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
堆排序
阅读量:6239 次
发布时间:2019-06-22

本文共 6188 字,大约阅读时间需要 20 分钟。

堆排序相对冒泡这些要复杂一些,它需要先初始化堆。.net里List的排序就混合使用了堆排序和另2种排序

 

出于学习目的,代码示范里不使用数组结构,数组取索引比较深涩。而使用嵌套类来实现。

 

 

 

1.初始化堆

 


 

排序肯定是有升序和降序两种,堆排序也一样,分为大顶堆和小顶堆。初始化堆的目的就是变为大顶堆或者小顶堆

传统的方法是取数组下标[n/2]向下取整,但直接取最后一个元素往前遍历也是可行的

下面用22,44,6,88,5几个数作为示范

 

step1.默认的树结构

 

step2.自顶向下,以22开始先比较44和6两个子树,比较方式可以先比较左子树和右子树,取最大的值再和父节点比较。

44和6先进行比较,44比较大。然后44再和22进行比较,发现比父节点大。然后执行交换

 

step3.然后比较22的两个子树,88比较大,执行交换

 

step4.由于内部执行了交换,再次进行遍历。发现88比44大,执行交换。

至此,初始化堆完成

 

 

2.执行排序


 

 

堆排序有一个有序区和无序区的概念,有序区同样在堆中,但是不参与排序。只有无序区参与排序,排序结果转移到有序区。

直到无序区没有之后,排序结束

 

step1.是初始化好的堆,没有进行任何操作

 

step2.需要不断的把第一个元素和最后一个元素进行交换,放入有序区,橙色的是有序区

 

step3.交换完成之后,再重复进行初始化堆,进行调整

 

step4.由于88是有序区的内容,所以只和左子树22比较后,进行交换。

 

step5.再次和第一个元素进行交换,加入到有序区。

 

 

 

 

堆排序完成

 

 

下面附上代码:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Hont{    public class HeapSort    {        public class Node        {            ///             /// 用了一下空对象模式,省去了判断null            ///             public readonly static Node EMPTY_NODE;            public Node LeftChild { get; set; }            public Node RightChild { get; set; }            public Node Parent { get; set; }            public int Value { get; set; }            public bool IsUsed { get; set; }            static Node()            {                EMPTY_NODE = new Node() { Value = 0, IsUsed = true };            }            public Node()            {                LeftChild = EMPTY_NODE;                RightChild = EMPTY_NODE;            }            public Node(Node parent)                : this()            {                this.Parent = parent;            }        }        ///         /// 执行排序        ///         /// 原始数组        /// 降序还是升序        /// 
排序后的数组
public int[] Sort(int[] sourceArray, bool maxOrMin = true) { Func
compare = null; if (maxOrMin) compare = (a, b) => a > b; else compare = (a, b) => a < b; var rootNode = BuildHeap(sourceArray.ToList()); AdjustHeap(rootNode, compare); SortHeap(rootNode, compare); return OutputHeap(rootNode).ToArray(); } ///
/// 构建堆,因为没有用数组去实现,需要额外构建 /// Node BuildHeap(List
sourceList) { Node result = new Node(); List
nextDepthNodeList = new List
(); List
tmpNextDepthNodeList = new List
(); BuildHeap(result, sourceList, nextDepthNodeList); for (int i = 0; i < nextDepthNodeList.Count; i++) { var item = nextDepthNodeList[i]; if (!BuildHeap(item, sourceList, tmpNextDepthNodeList)) { break; } if (i - 1 == nextDepthNodeList.Count) { nextDepthNodeList = tmpNextDepthNodeList; tmpNextDepthNodeList.Clear(); i = 0; } } var lastNode = GetLastSortNode(result); result.Value = lastNode.Value; if(lastNode.Parent.LeftChild == lastNode) { lastNode.Parent.LeftChild = Node.EMPTY_NODE; } else { lastNode.Parent.RightChild = Node.EMPTY_NODE; } return result; } bool BuildHeap(Node currentNode, List
sourceList, List
nextDepthNodeList) { if (sourceList.Count < 1) return false; var firstNode = sourceList[0]; currentNode.LeftChild = new Node(currentNode) { Value = firstNode }; nextDepthNodeList.Add(currentNode.LeftChild); sourceList.RemoveAt(0); if (sourceList.Count > 0) { var lastNode = sourceList[sourceList.Count - 1]; currentNode.RightChild = new Node(currentNode) { Value = lastNode }; nextDepthNodeList.Add(currentNode.RightChild); sourceList.RemoveAt(sourceList.Count - 1); } return true; } ///
/// 调整堆,调整至大顶堆或小顶堆,依据第二个参数 /// void AdjustHeap(Node heap, Func
compare) { if (heap == Node.EMPTY_NODE) return; if (heap.LeftChild.IsUsed && heap.RightChild.IsUsed) return; var leftChild = heap.LeftChild; var rightChild = heap.RightChild; var leftChildValue = heap.LeftChild.Value; var rightChildValue = heap.RightChild.Value; if (leftChild.IsUsed) leftChildValue = compare(int.MinValue, int.MaxValue) ? int.MaxValue : int.MinValue; if (rightChild.IsUsed) rightChildValue = compare(int.MinValue, int.MaxValue) ? int.MaxValue : int.MinValue; var selectChild = compare(leftChildValue, rightChildValue) ? leftChild : rightChild; var flag = compare(selectChild.Value, heap.Value); if (flag) { var tmp = heap.Value; heap.Value = selectChild.Value; selectChild.Value = tmp; } AdjustHeap(heap.LeftChild, compare); AdjustHeap(heap.RightChild, compare); if (flag) { AdjustHeap(heap, compare); } } void SortHeap(Node root, Func
compare) { while (!root.IsUsed) { var lastNode = GetLastSortNode(root); var tmpHeapValue = root.Value; root.Value = lastNode.Value; lastNode.Value = tmpHeapValue; lastNode.IsUsed = true; AdjustHeap(root, compare); } } ///
/// 获得最后可用的堆成员,如果是IsUsed说明是有序区就跳过,主要用于排序时,首尾成员交换 /// Node GetLastSortNode(Node root) { Node result = root; while (true) { if (result.RightChild != Node.EMPTY_NODE && !result.RightChild.IsUsed) { result = result.RightChild; } else if (result.LeftChild != Node.EMPTY_NODE && !result.LeftChild.IsUsed) { result = result.LeftChild; } else { break; } } return result; } ///
/// 遍历节点 /// void ForeachNode(Node root, Action
foreachContent) { if (root != Node.EMPTY_NODE) { foreachContent(root); } if (root.LeftChild != Node.EMPTY_NODE) { ForeachNode(root.LeftChild, foreachContent); } if (root.RightChild != Node.EMPTY_NODE) { ForeachNode(root.RightChild, foreachContent); } } List
OutputHeap(Node root) { List
result = new List
(); ForeachNode(root, m => m.IsUsed = false); while (!root.IsUsed) { var tmpNode = GetLastSortNode(root); result.Add(tmpNode.Value); tmpNode.IsUsed = true; } return result; } }}
Heap Sort

 

 

调用:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Hont;namespace HeapSortPackage{    class Program    {        static void Main(string[] args)        {            HeapSort heapSort = new HeapSort();            var result = heapSort.Sort(new int[] { 22, 44, 88, 5, 6 }, true);            Console.WriteLine(string.Join(",", result));            Console.Read();        }    }}
View Code

 

 

 

转载地址:http://nsdia.baihongyu.com/

你可能感兴趣的文章
用父类指针指向子类对象
查看>>
Flexigrid默认是可以选择多行
查看>>
PHP导入导出Excel方法小结
查看>>
ZOJ 3870 Team Formation 位运算 位异或用与运算做的
查看>>
清除浮动float的方法
查看>>
java学习第十二天
查看>>
1 Kubernetes管理之master和Node
查看>>
M端计算rem方法
查看>>
as3 用StyleSheet css 设置文本样式
查看>>
hdu4612(双连通缩点+树的直径)
查看>>
【转】深入理解 C# 协变和逆变
查看>>
第六次作业
查看>>
UML
查看>>
9.[Java开发之路](6)File类的使用
查看>>
折半插入排序(binary insertion sort)
查看>>
打包常见问题
查看>>
javascript解析json
查看>>
在Ubuntu下编译WebKit源码
查看>>
amazeui 移动开发
查看>>
python2 与python3中最大的区别(编码问题bytes&str
查看>>