堆排序递归和非递归

在了解堆排序之前,基本的二叉树的概念是需要知道的

完全二叉树:叶子节点在最后一层或者次一层,且节点从左往右连续
大根堆:任何根节点都比他的左右子节点都要大
i为节点在数组中的索引,求节点的父节点:(i - 1) / 2, 求节点的左节点 i * 2 + 1,求节点的右节点 i * 2 + 2

在构建一个堆之前,我们需要先把他们的左右节点构建成堆,所以我们从下往上依次构建堆,由于叶子节点是没有子节点的,所以从最后一个节点的父节点开始构建,想画个个图,可是实力实在不允许那就都放在代码中吧,老铁干了这段代码,先写递归的吧,递归毕竟理解起来简单。

	//测试方法
	@Test
    public void test() {
        int size = 50;
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = (int) (Math.random() * 100);
        }
        heapify2(array);
        System.out.println(Arrays.toString(array));
    }
    
    //堆排
    public void heapify2(int[] array) {
        if (array == null || array.length < 2) {
            return;
        }
        //最后一个节点的父节点
        int parentNode = (array.length - 2) / 2;

        //进行堆排
        for (int i = parentNode; i >= 0; i--) {
            sift2(array, i, array.length - 1);
        }

        //交换最后一个数和第一个数,交换后最大的数到最后,下次堆排的时候,最后一个数就不许算进去了
        for (int i = array.length - 1; i > 0 ; i--) {
            swap(array, 0, i);
            sift2(array, 0, i - 1);
        }
    }
	
	 /**
    * @Description 递归写法
    */
    public void sift2(int[] array, int currentNode, int length) {
        //左节点
        int left = currentNode * 2 + 1;
        //右节点
        int right = currentNode * 2 + 2;
		
		//如果左右节点有比当前节点要大的节点,后面是需要以这个节点进行堆排的
        int max = currentNode;

		//左节点不能超过数组的最大索引
        if (left <= length && array[left] > array[max]) {
            max = left;
        }

        if (right <= length && array[right] > array[max]) {
            max = right;
        }
		
		//如果发生交换,我们就需要进行堆排了
        if (max != currentNode) {
            swap(array, max, currentNode);
            //由于max指向的索引是最大的,和currentNode交换后,max现在指向的值就是currentNode的值了
            sift2(array, max, length);
        }

    }

最主要的就是这个sift,通过不断交换,来达到大根堆的效果,接着就是非递归的写法,其实和递归的思想一样,我们交换后就以交换的节点来进行堆排

	/**
    * @Description 非递归写法
    */
    public void sift1(int[] array, int currentNode, int length) {
    	//这个tmp就是当前需要堆排的节点,如果交换了,我们就让这个tmp等于交换的位置,来达到往下移一层
        int tmp = currentNode;
        //左节点
        int j = currentNode * 2 + 1;
        while (j <= length) {
            //比较左右大小
            if (j + 1 <= length && array[j + 1] > array[j]) {
                j = j + 1;
            }
            //由于左右已经进行比较了,所以我们只要于最大的比较
            if (array[tmp] < array[j]) {
                swap(array, tmp, j);
                //tmp往下移一层,tmp变成下一次需要堆排的节点
                tmp = j;
                //j接着等于需要堆排的左节点
                j = tmp * 2 + 1;
            } else {
                break;
            }
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个非递归实现的堆排序的 C++ 程序: ```cpp #include <iostream> #include <stack> using namespace std; void heapify(int arr[], int n, int i) { int largest = i; int l = 2 * i + 1; int r = 2 * i + 2; if (l < n && arr[l] > arr[largest]) largest = l; if (r < n && arr[r] > arr[largest]) largest = r; if (largest != i) { swap(arr[i], arr[largest]); heapify(arr, n, largest); } } void heapSort(int arr[], int n) { for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); stack<int> s; for (int i = n - 1; i >= 0; i--) { swap(arr[0], arr[i]); int j = 0; while (true) { int l = 2 * j + 1; int r = 2 * j + 2; int maxIndex = j; if (l < i && arr[l] > arr[maxIndex]) maxIndex = l; if (r < i && arr[r] > arr[maxIndex]) maxIndex = r; if (maxIndex != j) { swap(arr[j], arr[maxIndex]); s.push(j); j = maxIndex; } else if (!s.empty()) { j = s.top(); s.pop(); } else { break; } } } } void printArray(int arr[], int n) { for (int i = 0; i < n; ++i) cout << arr[i] << " "; cout << endl; } int main() { int arr[] = { 12, 11, 13, 5, 6, 7 }; int n = sizeof(arr) / sizeof(arr[0]); heapSort(arr, n); cout << "Sorted array is \n"; printArray(arr, n); } ``` 这个程序中,我们首先定义了两个函数 `heapify()` 和 `heapSort()` 来实现堆排序算法。 `heapify()` 函数用于维护最大堆的性质, `heapSort()` 函数则用于对堆进行排序。 在 `heapSort()` 函数中,我们首先构建一个最大堆,然后将堆顶元素(即最大元素)与堆中最后一个元素进行交换。然后我们使用一个栈 `s` 来记录需要进行 `heapify()` 操作的下标,然后从堆顶开始,依次将每个元素向下移动(通过不断交换元素),直到该元素达到其应该在的位置。当遇到需要交换的情况时,将下标压入栈中,继续向下移动;当元素已经到达正确位置,但栈不为空时,从栈中弹出一个下标继续向下移动;当元素已经到达正确位置且栈为空时,退出循环,进行下一次交换操作。 在 `printArray()` 函数中,我们用于输出排序后的结果。最后在 `main()` 函数中,我们定义了一个整型数组 `arr`,然后调用 `heapSort()` 函数对其进行排序,并输出排序后的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值