堆排序总结 以及优化

本文总结了排序算法的特点,重点讨论了堆排序。堆排序是一种原地排序算法,它利用堆这种数据结构进行排序。文章提到了堆排序的稳定性,并指出在某些情况下归并排序可以结合插入排序实现稳定排序。此外,文章还探讨了堆排序的优化,包括如何构建和调整堆,以及如何确定最大元素的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序算法总结:


1、原地排序:不需开辟额外空间,在数组本身进行排序
2、快速排序使用递归算法实现,递归 logn 层就需要 logn 层的栈空间来保存每次递归过程中的临时变量,以供递归返回的时候继续使用。
3、归并排序也使用了递归实现,额外空间应该是n+logn的,但由于logn<n,因此为O(n)
4、相等元素在排序前后相对位置未发生改变的称为稳定排序


排序算法的稳定性


排序算法的稳定性稳定排序:对于相等的元素,在排序后,原来的元素依然靠前,
注1  在n小于一定程度时,归并排序改用插入排序的融合算法,也是稳定排序.
注2  排序算法的稳定性与具体实现相关,若实现不好,可能会将插入级归并排序实现成不稳定的算法


优化~~

  • 一个数组可以看成一个堆
  • 最大元素应该放到数组末尾的位置
  • 堆的索引是从数组0的元素开始,而非1
  • parent(i) = (i-1)/2;
  • left child (i) = 2*i + 1;
  • right child (i) = 2*i + 2;

 

#include<iostream>
#include<algorithm>
using namespace std;
void __shiftDown(T arr[], int n, int k){
	while(2*k+1 <= n){
		int j = 2*k+1;
		if(j + 1 <= n && arr[j+1] > arr[j] ){/
			j+=1;  
		}
		if(arr[k] >= arr[j]){
			break;
		}
		swap(arr[k], arr[j])
		k=j;
	}
}

template<typename T>
void heapSort(T arr[], int n){
	
	//将arr数组构建成一个堆
	for(int i = (n-1)/2;i >= 0; i --){//子节点开始
		__shiftDown(arr, n , i);
	
	}
	for(int i = n-1;i>0;i--){
		swap(arr[0], arr[i]);
		__shiftDown(arr, i , 0);
	}
}
int main(){
	return 0;
}

 

 

索引堆

#include <iostream>
#include <cassert>
#include "SortTestHelper.h"

using namespace std;


template<typename Item>
class IndexMaxHeap{

private:
    Item *data;     
    int *indexes;   

    int count;
    int capacity;

    void shiftUp( int k ){

        while( k > 1 && data[indexes[k/2]] < data[indexes[k]] ){
            swap( indexes[k/2] , indexes[k] );
            k /= 2;
        }
    }

   void shiftDown( int k ){

        while( 2*k <= count ){
            int j = 2*k;
            if( j + 1 <= count && data[indexes[j+1]] > data[indexes[j]] )
                j += 1;
			
            if( data[indexes[k]] >= data[indexes[j]] )
                break;

            swap( indexes[k] , indexes[j] );
            k = j;
        }
    }

public: 
		IndexMaxHeap(int capacity){

        data = new Item[capacity+1];
        indexes = new int[capacity+1];

        count = 0;
        this->capacity = capacity;
    }

    ~IndexMaxHeap(){
        delete[] data;
        delete[] indexes;
    }

    int size(){
        return count;
    }


    bool isEmpty(){
        return count == 0;
    }
	//传入的i堆用户而言,是从0索引的。
    void insert(int i, Item item){
        assert( count + 1 <= capacity );
        assert( i + 1 >= 1 && i + 1 <= capacity );

        i += 1;
        data[i] = item;
        indexes[count+1] = i;
        count++;

        shiftUp(count);
    }

    Item extractMax(){
        assert( count > 0 );

        Item ret = data[indexes[1]];
        swap( indexes[1] , indexes[count] );
        count--;
        shiftDown(1);
        return ret;
    }

    int extractMaxIndex(){
        assert( count > 0 );
		//拿到最大元素
        int ret = indexes[1] - 1;
        swap( indexes[1] , indexes[count] );
        count--;
        shiftDown(1);
        return ret;
    }

    Item getMax(){
        assert( count > 0 );
        return data[indexes[1]];
    }

   int getMaxIndex(){
        assert( count > 0 );
        return indexes[1]-1;
    }

   Item getItem( int i ){
        assert( i + 1 >= 1 && i + 1 <= capacity );
        return data[i+1];
    }

     void change( int i , Item newItem ){

        i += 1;
        data[i] = newItem;

        for( int j = 1 ; j <= count ; j ++ )
            if( indexes[j] == i ){
                shiftUp(j);
                shiftDown(j);
                return;
            }
    }

    bool testIndexes(){

        int *copyIndexes = new int[count+1];

        for( int i = 0 ; i <= count ; i ++ )
            copyIndexes[i] = indexes[i];

        copyIndexes[0] = 0;
        std::sort(copyIndexes, copyIndexes + count + 1);

         bool res = true;
        for( int i = 1 ; i <= count ; i ++ )
            if( copyIndexes[i-1] + 1 != copyIndexes[i] ){
                res = false;
                break;
            }

        delete[] copyIndexes;

        if( !res ){
            cout<<"Error!"<<endl;
            return false;
        }

        return true;
    }
};

template<typename T>
void heapSortUsingIndexMaxHeap(T arr[], int n){

    IndexMaxHeap<T> indexMaxHeap = IndexMaxHeap<T>(n);
    for( int i = 0 ; i < n ; i ++ )
        indexMaxHeap.insert( i , arr[i] );
    assert( indexMaxHeap.testIndexes() );

    for( int i = n-1 ; i >= 0 ; i -- )
        arr[i] = indexMaxHeap.extractMax();
}

int main() {

    int n = 1000000;

    int* arr = SortTestHelper::generateRandomArray(n, 0, n);
    SortTestHelper::testSort("Heap Sort Using Index-Max-Heap", heapSortUsingIndexMaxHeap, arr, n);
    delete[] arr;

    return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值