zoukankan      html  css  js  c++  java
  • 二叉堆-顺序存储

    数组实现二叉堆




    创建3个文件:heapArray.h、heapArray.c、heapArrayTest.c




    heapArray.h
    #ifndef HEAP_ARRAY_H_
    #define HEAP_ARRAY_H_
    
    #ifdef __GNUC__
    	#define DEPRECATED __attribute__( (deprecated) )
    #elif defined(_MSC_VER)
    	#define DEPRECATED __declspec( deprecated )
    #else
    	#define DEPRECATED
    #endif
    
    #ifndef PTOI
    	#define PTOI( p ) ((int32_t)(int64_t)(p))
    #endif
    #ifndef ITOP
    	#define ITOP( i ) ((void *)(int64_t)(i))
    #endif
    
    #define ADT HeapArray
    
    // 功能: a与b的比较过程.
    // 参数: a, b.
    // 返回: a>b返回正数, a<b返回负数, 否则返回0.
    // 注意: a不为NULL且b为NULL,返回正数, a为NULL且b不为NULL,返回负数, a与b都为NULL,返回0.
    typedef int ( CompareFunc )( const void *a, const void *b );
    
    typedef struct HeapArray HeapArray;
    
    // 功能: 创建一个新的堆.
    // 参数: capacity(堆的最大容量), cmp(数据比较函数的指针).
    // 返回: 一个新的堆.
    // 注意: 当 capacity 小于0时,默认为512; 当内存分配失败时,将错误退出程序.
    extern ADT *newHeapArray( int32_t capacity, CompareFunc *cmp );
    
    // 功能: 将用户数据加入到堆底.
    // 参数: heap(堆对象的指针), data(用户数据).
    // 返回: 被加入到堆底的用户数据.
    // 注意: 当 heap 为NULL 或 满堆状态 时, 将错误退出程序.
    extern void *addHeapArray( ADT *heap, void *data );
    
    // 功能: 将用户数据加入到堆顶.
    // 参数: heap(堆对象的指针), data(用户数据).
    // 返回: 被加入到堆顶的用户数据.
    // 注意: 当 heap 为NULL 或 满堆状态 时, 将错误退出程序.
    // 被弃用的函数.
    extern DEPRECATED void *addHeadHeapArray( ADT *heap, void *data );
    
    // 功能: 移除堆顶用户数据.
    // 参数: heap(堆对象的指针).
    // 返回: 被移除的堆顶的用户数据.
    // 注意: 当 heap 为NULL 或 空堆状态 时, 将错误退出程序.
    extern void *pollHeapArray( ADT *heap );
    
    // 功能: 移除堆底用户数据.
    // 参数: heap(堆对象的指针).
    // 返回: 被移除的堆底的用户数据.
    // 注意: 当 heap 为NULL 或 空堆状态 时, 将错误退出程序.
    extern void *pollTailHeapArray( ADT *heap );
    
    // 功能: 偷看堆顶的用户数据.
    // 参数: heap(堆对象的指针).
    // 返回: 堆顶的用户数据.
    // 注意: 当 heap 为NULL 或 空堆状态 时, 将错误退出程序.
    extern void *peekHeapArray( ADT *heap );
    
    // 功能: 偷看堆底的用户数据.
    // 参数: heap(堆对象的指针).
    // 返回: 堆底的用户数据.
    // 注意: 当 heap 为NULL 或 空堆状态 时, 将错误退出程序.
    extern void *peekTailHeapArray( ADT *heap );
    
    
    // 功能: 堆中所有用户数据中是否包含了data.
    // 参数: heap(堆对象的指针), data(需查找的用户数据).
    // 返回: 包含了data返回1, 否则返回0.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int existHeapArray( ADT *heap, void *data );
    
    // 功能: 从堆顶至堆底方向查找data.
    // 参数: heap(堆对象的指针), data(需查找的用户数据).
    // 返回: 堆中包含了data, 返回data所在位置, 否则返回-1.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int32_t findHeapArray( ADT *heap, void *data );
    
    // 功能: 从堆底至堆顶方向查找data.
    // 参数: heap(堆对象的指针), data(需查找的用户数据).
    // 返回: 堆中包含了data, 返回data所在位置, 否则返回-1.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int32_t findTailHeapArray( ADT *heap, void *data );
    
    // 功能: 堆实际已使用大小.
    // 参数: heap(堆对象的指针).
    // 返回: 堆实际已使用大小.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int32_t sizeHeapArray( ADT *heap );
    
    // 功能: 空堆状态.
    // 参数: heap(堆对象的指针).
    // 返回: 是空堆返回1, 否则返回0.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int emptyHeapArray( ADT *stsack );
    
    // 功能: 满堆状态.
    // 参数: heap(堆对象的指针).
    // 返回: 是满堆返回1, 否则返回0.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int fullHeapArray( ADT *heap );
    
    // 功能: 堆最大容量.
    // 参数: heap(堆对象的指针).
    // 返回: 堆最大容量.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern int32_t capacityHeapArray( ADT *heap );
    
    // 功能: 清空堆.
    // 参数: heap(堆对象的指针).
    // 返回: 无.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern void clearHeapArray( ADT *heap );
    
    // 功能: 销毁堆.
    // 参数: heap(存放堆对象的指针的指针).
    // 返回: 无.
    // 注意: 当 heap 为NULL 时, 将错误退出程序.
    extern void delHeapArray( ADT **heap );
    
    #undef ADT
    
    #endif
    

    heapArray.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include "heapArray.h"
    
    
    // 功能: 打印错误信息后就错误退出程序.
    // 参数: expression(错误判断表达式), message(需打印的错误信息).
    // 返回: 无.
    // 注意: 当表达式 expression 为真时, 才触发.
    #define ERROR_EXIT( expression, message )                                    
    if( (expression) ) {                                                         
    	fprintf( stderr, "
    error location: file = %s, func = %s, line = %d.
    ", 
    	                       __FILE__, __func__, __LINE__ );                   
    	fprintf( stderr, "error  message: %s%s.
    a",                            
    	                       (message) != NULL ? (message) : __func__,         
    		                   (message) != NULL ? "" : " function error" );     
    	exit( EXIT_FAILURE );                                                    
    }
    
    // 功能: 数组的两个元素进行互换.
    // 参数: a(数组首地址), i(数组下标), j(数组下标).
    // 返回: 无.
    // 注意: 没有副作用的宏, C99标准: #define f ({...}).
    #define SWAP( a, i, j ) ({            
    	int32_t i1i1i = (i), j1j1j = (j); 
    	void *t1t1t = *((a) + i1i1i);     
    	*((a) + i1i1i) = *((a) + j1j1j);  
    	*((a) + j1j1j) = t1t1t;           
    })
    
    #define ADT HeapArray
    
    
    struct HeapArray {
    	int32_t capacity;
    	int32_t size;
    	CompareFunc *cmp;
    	void *array[0];
    };
    
    
    ADT *newHeapArray( int32_t capacity, CompareFunc *cmp ) {
    	ADT *heap = NULL;
    
    	ERROR_EXIT( !cmp, NULL );
    	capacity = capacity < 0 ? 512 : capacity;
    	heap = malloc( sizeof(*heap) + sizeof(heap->array[0]) * capacity );
    	ERROR_EXIT( !heap, NULL );
    	heap->capacity = capacity;
    	heap->size = 0;
    	heap->cmp = cmp;
    
    	return heap;
    }
    
    void *addHeapArray( HeapArray *heap, void *data ) {
    	int32_t i = 0;
    
    	ERROR_EXIT( !heap || heap->size >= heap->capacity, NULL );
    	i = heap->size++;
    	heap->array[i] = data;
    
    	for( int32_t p = (i - 1) / 2; heap->cmp( heap->array[i], heap->array[p] ) < 0; p = (i - 1) / 2 ) {
    		// i: index, p: parent.
    		SWAP( heap->array, p, i );
    		i = p;
    	}
    
    	return data;
    }
    
    void *addHeadHeapArray( HeapArray *heap, void *data ) {
    	return NULL;
    }
    
    void *pollHeapArray( HeapArray *heap ) {
    	int32_t i = 0;
    
    	ERROR_EXIT( !heap || heap->size < 1, NULL );
    	SWAP( heap->array, 0, heap->size - 1 ); // 堆顶与堆底进行对换.
    	--heap->size;
    	for( int32_t l = i * 2 + 1; l < heap->size; l = i * 2 + 1 ) { // 从堆顶至堆底方向进行调整.
    		// l: left child, r: right child, m: maximum or minimum.
    		int32_t r = l + 1, m = l;
    		if( r < heap->size && heap->cmp( heap->array[r], heap->array[l] ) < 0 ) {
    			m = r;
    		}
    		if( heap->cmp( heap->array[i], heap->array[m] ) <= 0 ) {
    			break;
    		}
    		SWAP( heap->array, m, i );
    		i = m;
    	}
    
    	return heap->array[heap->size];
    }
    
    void *pollTailHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap || heap->size < 1, NULL );
    
    	return heap->array[--heap->size];
    }
    
    void *peekHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap || heap->size < 1, NULL );
    
    	return heap->array[0];
    }
    
    void *peekTailHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap || heap->size < 1, NULL );
    
    	return heap->array[heap->size - 1];
    }
    
    int existHeapArray( HeapArray *heap, void *data ) {
    	ERROR_EXIT( !heap, NULL );
    
    	for( int32_t i = 0; i < heap->size; ++i ) {
    		if( !heap->cmp( heap->array[i], data ) ) {
    			return 1;
    		}
    	}
    
    	return 0;
    }
    
    int32_t findHeapArray( HeapArray *heap, void *data ) {
    	ERROR_EXIT( !heap, NULL );
    	for( int32_t i = 0; i < heap->size; ++i ) {
    		if( !heap->cmp( heap->array[i], data ) ) {
    			return i;
    		}
    	}
    
    	return -1;
    }
    
    int32_t findTailHeapArray( HeapArray *heap, void *data ) {
    	ERROR_EXIT( !heap, NULL );
    	for( int32_t i = heap->size - 1; i >= 0; --i ) {
    		if( !heap->cmp( heap->array[i], data ) ) {
    			return i;
    		}
    	}
    
    	return -1;
    }
    
    int32_t sizeHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap, NULL );
    
    	return heap->size;
    }
    
    int emptyHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap, NULL );
    
    	return heap->size < 1;
    }
    
    int fullHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap, NULL );
    
    	return heap->size >= heap->capacity;
    }
    
    int32_t capacityHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap, NULL );
    
    	return heap->capacity;
    }
    
    void clearHeapArray( HeapArray *heap ) {
    	ERROR_EXIT( !heap, NULL );
    
    	heap->size = 0;
    }
    
    void delHeapArray( HeapArray **heap ) {
    	ERROR_EXIT( !heap, NULL );
    	free( *heap );
    	*heap = NULL;
    }
    

    heapArrayTest.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <time.h>
    #include "heapArray.h"
    
    
    // a>b返回正数, a<b返回负数, 否则返回0.
    static int cmp( const void *a, const void *b ) {
    	return *(int32_t *) a - *(int32_t *) b;
    }
    
    int main( int argc, char *argv[] ) {
    	char *tf[] = {"false", "true"};
    	int32_t *a = NULL, n = 0;
    	int32_t i = 0, k = 0;
    	HeapArray *h = NULL;
    
    	srand( time( NULL ) );
    	printf( "please input array length: n = " );
    	scanf( "%d%*c", &n );
    	printf( "
    " );
    
    	a = malloc( sizeof(*a) * n );
    	for( i = 0; i < n; ++i ) {
    		a[i] = rand() % 322;
    		//a[i] = 1;
    	}
    	a[0] = 52; a[1] = 134; a[2] = 93; a[3] = 4; a[4] = 195;
    
    	printf( "&h = %p, h = %p
    ", &h, h );
    	h = newHeapArray( n, cmp );
    	printf( "new: &h = %p, h = %p
    ", &h, h );
    
    	printf( "peek       = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekHeapArray( h ) );
    	printf( "peekTail = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekTailHeapArray( h ) );
    	printf( "size     = %d
    ", sizeHeapArray( h ) );
    	printf( "empty = %s
    ", tf[emptyHeapArray( h )]);
    	printf( "full  = %s
    ", tf[fullHeapArray( h )] );
    	printf( "capacity = %d
    ", capacityHeapArray( h ) );
    	printf( "
    " );
    
    	for( i = 0; i < n; ++i ) {
    		printf( "add: %d
    ", *(int32_t *) addHeapArray( h, &a[i] ) );
    	}
    	printf( "
    " );
    
    	printf( "peek       = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekHeapArray( h ) );
    	printf( "peekTail = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekTailHeapArray( h ) );
    	printf( "size     = %d
    ", sizeHeapArray( h ) );
    	printf( "empty = %s
    ", tf[emptyHeapArray( h )] );
    	printf( "full  = %s
    ", tf[fullHeapArray( h )] );
    	printf( "capacity = %d
    ", capacityHeapArray( h ) );
    	printf( "
    " );
    
    	//k = a[0];
    	k = rand();
    	printf( "exist &k(%d) = %s
    ", k, tf[existHeapArray( h, &k )] );
    	printf( "
    " );
    
    	k = a[0];
    	//k = rand();
    	printf( "find &k(%d) = %d
    ", k, findHeapArray( h, &k ) );
    	printf( "
    " );
    
    	//k = a[0];
    	k = rand();
    	printf( "findTile &k(%d) = %d
    ", k, findTailHeapArray( h, &k ) );
    	printf( "
    " );
    
    	for( i = 0; !emptyHeapArray( h ); ++i ) {
    		if( i & 1 ) {
    			printf( "poll: %d
    ", *(int32_t *) pollHeapArray( h ) );
    		} else {
    			printf( "pollTail %d
    ", *(int32_t *) pollTailHeapArray( h ) );
    		}
    		//printf( "peek       = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekHeapArray( h ) );
    		//printf( "peekTail = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekTailHeapArray( h ) );
    		//printf( "size     = %d
    ", sizeHeapArray( h ) );
    		//printf( "empty = %s
    ", tf[emptyHeapArray( h )] );
    		//printf( "full  = %s
    ", tf[fullHeapArray( h )] );
    		//printf( "capacity = %d
    ", capacityHeapArray( h ) );
    		//printf( "
    " );
    	}
    	printf( "
    " );
    
    	printf( "peek       = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekHeapArray( h ) );
    	printf( "peekTail = %d
    ", emptyHeapArray( h ) ? INT32_MIN : *(int32_t *) peekTailHeapArray( h ) );
    	printf( "size     = %d
    ", sizeHeapArray( h ) );
    	printf( "empty = %s
    ", tf[emptyHeapArray( h )] );
    	printf( "full  = %s
    ", tf[fullHeapArray( h )] );
    	printf( "capacity = %d
    ", capacityHeapArray( h ) );
    	printf( "
    " );
    
    	delHeapArray( &h );
    	printf( "del: &h = %p, h = %p
    ", &h, h );
    
    	return EXIT_SUCCESS;
    }
    



  • 相关阅读:
    MD5算法--网盘秒传
    无线网络定位算法综述
    android学习---异步任务(AsyncTask)
    python中局部变量的定义
    python3里函数怎么样使用元组或字典作为参数调用(复制他人博客)
    调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之一
    Linux入门之——安装虚拟机软件
    Linux学习方法之以始为终—Linux工作分类
    Linux基础系列—Linux内核源码目录结构
    Linux基础系列—Linux体系结构和Linux内核结构
  • 原文地址:https://www.cnblogs.com/hujunxiang98/p/12882405.html
Copyright © 2011-2022 走看看