zoukankan      html  css  js  c++  java
  • 堆排序演示 ( 这个 堆排函数将适合所有的堆排, 只需要改一下比较函数)

    通用的堆排函数思想 :

    1.对任意一个点进行调整, 需要往两个方向, 父节点和左右子节点进行比较, 交换

    2.传入不同的比较函数使得函数变成通用的

    对一堆数据,需要用堆排: 

    (1). 插入方法建堆 (实际工作中这种是更常见)

    (2). 基于当前数组进行建堆

    比较函数 , 交换函数, 打印函数 :

    #include "common.h"
    
    /**
    * heap_size 此次调整堆的最大元素个数(因为堆排序过程中,后面已经调整好的就不需要调整了)
    * pos 表示此次调整堆的节点
    * */
    
    typedef struct Heap
    {
    	int heap[100];
    	int tail;
    }Heap;
    
    static int Compare(int idA, int idB)
    {
    	return idA - idB;
    }
    
    //交换堆中任意两个数
    static void Swap(Heap *pheap, int posA, int posB)
    {
    	int ID1 = pheap->heap[posB];
    	int ID2 = pheap->heap[posA];
    	pheap->heap[posA] = ID2;
    	pheap->heap[posB] = ID1;
    }
    
    //打印堆中的数据
    static void printHeap(Heap *pheap)
    {
    	for (int i = 1; i < pheap->tail; i++) //从 index = 1 开始保存数据
    	{
    		printf("%d ", pheap->heap[i]);
    	}
    	printf("
    
    ");
    }
    

     

    通用的 堆 调整函数 :

    #define parent (pos >> 1) //获得该父节点的左孩子
    #define left   (pos << 1)   //获得该父节点的左孩子
    #define right  (pos*2 + 1)  //获得该父节点的右孩子, 为啥不能((pos<<2) + 1)
    
    static void adjustHeap(Heap *pheap, int pos, int Compare(int idA, int idB)) // heap_size --> tail
    {
    	if (pos <= 0)
    	{
    		return;
    	}
    
    	int old_pos = pos;
    
    	while (pos > 1 && Compare(pheap->heap[parent], pheap->heap[pos]) < 0)
    	{
    		Swap(pheap, pos, parent);
    		pos = parent;
    	}
    
    	pos = old_pos;
    
    	while ((left < pheap->tail && Compare(pheap->heap[left], pheap->heap[pos]) > 0)
    		|| (right < pheap->tail && Compare(pheap->heap[right], pheap->heap[pos]) > 0))
    	{
    		if ((left < pheap->tail && Compare(pheap->heap[left], pheap->heap[pos]) > 0)
    			&& (right < pheap->tail && Compare(pheap->heap[right], pheap->heap[pos]) > 0))
    		{
    			if (Compare(pheap->heap[left], pheap->heap[right]) > 0) {
    				Swap(pheap, pos, left);
    				pos = left;
    			}
    			else
    			{
    				Swap(pheap, pos, right);
    				pos = right;
    			}
    		}// tail == 12 的时候, pos = 6, 又跟已经交换到 12 的值为 18 的元素交换, 所以不能用 <=
    		else if (left < pheap->tail && Compare(pheap->heap[left], pheap->heap[pos]) > 0)
    		{
    			Swap(pheap, pos, left);
    			pos = left;
    		}
    		else if (right < pheap->tail && Compare(pheap->heap[right], pheap->heap[pos]) > 0)
    		{
    			Swap(pheap, pos, right);
    			pos = right;
    		}
    	}
    }
    

      

    插入式建堆 :

    static void maxHeapInsert(Heap *pheap, int key)
    {
    	int old_pos = pheap->tail;
    	pheap->heap[old_pos] = key;
    	pheap->tail++;
    	adjustHeap(pheap, old_pos, Compare);  //在哪个节点插入就更新那个节点
    }
    
    extern void test_heap_qfh()
    {
    	//simple test
    	int arr[] = { 20,14,10,8,7,9,3,2,4,1,80,50,40,70,11,19,12,18,23,35,22 };  // 这个不考虑 0 号元素, 可能好一点
    	int len = sizeof(arr) / sizeof(arr[0]); // no need to consider number 0, so the len is 9 only
    	printf("%s %d : arr len = %d 
    ", __FUNCTION__, __LINE__, len);
    
    	Heap heap;
    	heap.heap[0] = 0; // 源数组是有值的
    	heap.tail = 1; // 从 0 开始计算, 才满足 父节点 = i , 左子节点 = 2*i, 右子节点 = 2*i + 1
    
    	LOGE("will build max heap");
    	//build heap (插入式创建 heap)
    	for (int i = 0; i < len; i++)
    	{
    		maxHeapInsert(&heap, arr[i]);
    		printHeap(&heap);
    	}
    
    	LOGE("will sort all the heap");
    	for (int heap_size = len; heap_size >= 2; heap_size--) // heap_size is size of not sort of heap , from tail-1 to 1
    	{
    		heap.tail--; //先将 tail - 1, 因为 tail-1 才是保存有数据的
    		Swap(&heap, 1, heap.tail);//将堆顶元素(通过调整堆获得的最大值)和最后一个交换(剩余未排好序部分的最后一个)
    		adjustHeap(&heap, 1, Compare);//之后每次从堆顶开始调整,最大的值将上升到根节点
    		printHeap(&heap);
    	}
    heap.tail = len + 1; printHeap(&heap); }

      

    进队 :

    test_heap_qfh 101 : arr len = 21
    e:c++c_testc_testheap_sort_not_use0-qfh.cpp test_heap_qfh 107 : will build max heap
    20
    
    20 14
    
    20 14 10
    
    20 14 10 8
    
    20 14 10 8 7
    
    20 14 10 8 7 9
    
    20 14 10 8 7 9 3
    
    20 14 10 8 7 9 3 2
    
    20 14 10 8 7 9 3 2 4
    
    20 14 10 8 7 9 3 2 4 1
    
    80 20 10 8 14 9 3 2 4 1 7
    
    80 20 50 8 14 10 3 2 4 1 7 9
    
    80 20 50 8 14 40 3 2 4 1 7 9 10
    
    80 20 70 8 14 40 50 2 4 1 7 9 10 3
    
    80 20 70 8 14 40 50 2 4 1 7 9 10 3 11
    
    80 20 70 19 14 40 50 8 4 1 7 9 10 3 11 2
    
    80 20 70 19 14 40 50 12 4 1 7 9 10 3 11 2 8
    
    80 20 70 19 14 40 50 12 18 1 7 9 10 3 11 2 8 4
    
    80 23 70 20 14 40 50 12 19 1 7 9 10 3 11 2 8 4 18
    
    80 35 70 20 23 40 50 12 19 14 7 9 10 3 11 2 8 4 18 1
    
    80 35 70 20 23 40 50 12 19 22 7 9 10 3 11 2 8 4 18 1 14  //这是大顶堆 , 实际排序后将跟最后一个未排数据进行交换, 最终得到的数据是 从小到大排列
    

      

    index 1 和 index = tail-1 进行交换 :

    e:c++c_testc_testheap_sort_not_use0-qfh.cpp test_heap_qfh 115 : will sort all the heap
    70 35 50 20 23 40 14 12 19 22 7 9 10 3 11 2 8 4 18 1
    
    50 35 40 20 23 10 14 12 19 22 7 9 1 3 11 2 8 4 18
    
    40 35 18 20 23 10 14 12 19 22 7 9 1 3 11 2 8 4
    
    35 23 18 20 22 10 14 12 19 4 7 9 1 3 11 2 8
    
    23 22 18 20 8 10 14 12 19 4 7 9 1 3 11 2
    
    22 20 18 19 8 10 14 12 2 4 7 9 1 3 11
    
    20 19 18 12 8 10 14 11 2 4 7 9 1 3
    
    19 12 18 11 8 10 14 3 2 4 7 9 1
    
    18 12 14 11 8 10 1 3 2 4 7 9
    
    14 12 10 11 8 9 1 3 2 4 7
    
    12 11 10 7 8 9 1 3 2 4
    
    11 8 10 7 4 9 1 3 2
    
    10 8 9 7 4 2 1 3
    
    9 8 3 7 4 2 1
    
    8 7 3 1 4 2
    
    7 4 3 1 2
    
    4 2 3 1
    
    3 2 1
    
    2 1
    
    1
    

      

    最终拍好的数据 :

    1 2 3 4 7 8 9 10 11 12 14 18 19 20 22 23 35 40 50 70 80
    

      

  • 相关阅读:
    Find the Smallest K Elements in an Array
    Count of Smaller Number
    Number of Inversion Couple
    Delete False Elements
    Sort Array
    Tree Diameter
    Segment Tree Implementation
    Java Programming Mock Tests
    zz Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
    Algorithm about SubArrays & SubStrings
  • 原文地址:https://www.cnblogs.com/Pitter99/p/14979510.html
Copyright © 2011-2022 走看看