数据结构之最小/大堆

来源:互联网 发布:matlab支持c语言吗 编辑:程序博客网 时间:2024/05/14 23:24


// Heap.h#ifndef HEAP_H#define HEAP_H// 当前平台#define WINDOWS_VISUALSTUDIO// #define LINUX_GCC// #define MACOS_XCODE#ifdef WINDOWS_VISUALSTUDIO#define _CRT_SECURE_NO_WARNINGS#include <conio.h>#endif#include <stdio.h>#include <stdlib.h>typedef enum { false, true } bool;typedef char ElemNumb;// 顺序表数目单位typedef int Key;typedef struct{Key KeyValue; // 此处随元素属性而改变// 此处可添加其他数据类型}ArrayItem;typedef struct{ArrayItem *base; // 数组地址ElemNumb size;// 数组当前长度ElemNumb MaxSize; // 数组最大长度bool kind; // 堆类型 0为最小堆 1为最大堆const char * FileName; // 向文件输出元素的文件名}ArrayList;void AdjustHeap(ArrayList * const H);void UnusualToExit(const char * const str, const char * const FileName);#endif

// Heap.c#include "Heap.h"#include "ArrayOfHeap.h"const char * const NullPointer = "空指针\n";static void ShiftDown(ArrayList * const H, ElemNumb k);// 将堆调整成最小/大堆void AdjustHeap(ArrayList * const H){// if (H != NULL)if (H){if (H->size > 1){ElemNumb i;// for (i = ((H->size) / 2) - 1; ; --i)for (i = (((H->size) >> 1) - 1); ; --i) // i为堆中非叶结点的数组索引{// 将H->base[i]插入H->base[i + 1] 至 H->base[H->size - 1]的最小/大堆中ShiftDown(H, i);// if (i == 0)if (!i)break;}}}// if (H == NULL)elseUnusualToExit(NullPointer, NULL);}void UnusualToExit(const char * const str, const char * const FileName){// if (str != NULL)if (str){fprintf(stderr, str, FileName);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}/*************************** 私有函数 **************************/// 将H->base[k]插入H->base[k + 1] 至 H->base[(H->size) - 1]的最小/大堆中static void ShiftDown(ArrayList * const H, ElemNumb k){// if (H != NULL)if (H){ElemNumb j;ArrayItem temp = H->base[k];// 连续交换用循环传递实现// for (j = 2 * k + 1; j < H->size; k = j, j = 2 * k + 1)for (j = (k << 1) + 1; j < H->size; k = j, j = (k << 1) + 1){// if (H->kind == true)if (H->kind) // 最大堆{if ((j < (H->size) - 1) && (H->base[j].KeyValue < H->base[j + 1].KeyValue))++j;if (temp.KeyValue >= H->base[j].KeyValue)break;}// if (H->kind == false)else // 最小堆{if ((j < (H->size) - 1) && (H->base[j].KeyValue > H->base[j + 1].KeyValue))++j;if (temp.KeyValue <= H->base[j].KeyValue)break;}H->base[k] = H->base[j]; // 循环传递中}H->base[k] = temp; // 循环传递结束}// if (H == NULL)elseUnusualToExit(NullPointer, NULL);}

// 数组顺序表// ArrayOfHeap.h#ifndef ARRAY_OF_HEAP_H#define ARRAY_OF_HEAP_H#include "heap.h"#define EOF_OPERATION "\nPlease enter:\tPress Ctrl + %c in new line to end\n"#define READ_OPERATION "r"#define WRITE_0PERATION "w"#define MEMORY_ERROR "Memory is not enough !\n"void CreateListByArray(ArrayList * const Array, const ElemNumb Max, const bool kind, const char * const FileName);void DestroyListByArray(ArrayList * const Array);bool ListByArrayIsEmpty(const ArrayList * const Array);bool ListByArrayIsFull(const ArrayList * const Array);void InputListByArrayFromFile(ArrayList * const Array);void InputListByArrayFromKeyboard(ArrayList * const Array, FILE * const stream);void OutputListByArrayToFile(const ArrayList * const Array);void OutputListByArrayToMonitor(const ArrayList * const Array, FILE * const stream);void AddHeadListByArray(ArrayList * const Array, const ArrayItem * const NewItem);void AddTailListByArray(ArrayList * const Array, const ArrayItem * const NewItem);void AddListByArray(ArrayList * const Array, const ElemNumb order, const ArrayItem * const NewItem);void DelHeadListByArray(ArrayList * const Array, ArrayItem * const DelItem);void DelTailListByArray(ArrayList * const Array, ArrayItem * const DelItem);void DelOrderListByArray(ArrayList * const Array, const ElemNumb order, ArrayItem * const DelItem);ElemNumb SearchListByArray(const ArrayList * const Array, const Key SearchKey);void DelSearchListByArray(ArrayList * const Array, const Key DelKey);/********************************* 队列操作 *************************************/// 入队void EnQueueByArray(ArrayList * const Array, ArrayItem *NewItem);// 出队void DeQueueByArray(ArrayList * const Array, ArrayItem *DelItem);/********************************* 堆栈操作 *************************************/void PushByArray(ArrayList * const Array, ArrayItem * const NewItem);void PopByArray(ArrayList * const Array, ArrayItem * const DelItem);void GetTopOfStackByArray(const ArrayList * const Array, ArrayItem * const TopItem);#endif

// ArrayOfHeap.c#include "ArrayOfHeap.h"extern const char * const NullPointer;static const char * const OpemFileError = "can not open %s !\n";static const char * const CloseFileError = "Error in closing file %s\n";static const char * const InsertError = "插入位置非法\n";static const char * const EmptyArray = "空数组\n";static const char * const FullArray = "已至数量极限值 请扩充ElemNumb数据单位!\n";static const char ImpossibleValue = -1;// 创建空顺序表Arrayvoid CreateListByArray(ArrayList * const Array, const ElemNumb Max, const bool kind, const char * const FileName){// if (Array != NULL)if (Array){Array->base = (ArrayItem *)malloc(Max * sizeof(ArrayItem));// if (Array->base != NULL)if (Array->base){Array->size = 0; // 空表长度置0Array->MaxSize = Max;Array->kind = kind;Array->FileName = FileName;}// if (Array->base == NULL)elseUnusualToExit(MEMORY_ERROR, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void DestroyListByArray(ArrayList * const Array){// if (Array != NULL)if (Array){free(Array->base);Array->base = NULL;Array->size = Array->MaxSize = 0;Array->FileName = NULL;}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}bool ListByArrayIsEmpty(const ArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == 0;// if (Array == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}bool ListByArrayIsFull(const ArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == Array->MaxSize;// if (Array == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 文件输入void InputListByArrayFromFile(ArrayList * const Array){// if (Array != NULL)if (Array){// if (Array->FileName != NULL && READ_OPERATION != NULL)if (Array->FileName && READ_OPERATION){FILE *fp = fopen(Array->FileName, READ_OPERATION);// if (fp != NULL)if (fp)InputListByArrayFromKeyboard(Array, fp);// if (fp == NULL)elseUnusualToExit(OpemFileError, Array->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);}}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}// 键盘输入void InputListByArrayFromKeyboard(ArrayList * const Array, FILE * const stream){// if (Array != NULL && stream != NULL)if (Array && stream){if (stream == stdin){#ifdef WINDOWS_VISUALSTUDIOprintf(EOF_OPERATION, 'z');#endif#ifdef LINUX_GCCprintf(EOF_OPERATION, 'd');#endif#ifdef MACOS_XCODEprintf(EOF_OPERATION, 'd');#endif}ArrayItem temp;// while (feof(stream) == 0)while (!feof(stream)){if (fscanf(stream, "%d\n", &temp.KeyValue) != EOF) // 此处随元素属性而改变AddTailListByArray(Array, &temp);}}// if (Array == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 文件输出void OutputListByArrayToFile(const ArrayList * const Array){// if (Array != NULL)if (Array){// if (Array->FileName != NULL && WRITE_0PERATION != NULL)if (Array->FileName && WRITE_0PERATION){FILE *fp = fopen(Array->FileName, WRITE_0PERATION);// if (fp != NULL)if (fp)OutputListByArrayToMonitor(Array, fp);// if (fp == NULL)elseUnusualToExit(OpemFileError, Array->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);}}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}// 输出顺序表List的所有元素void OutputListByArrayToMonitor(const ArrayList * const Array, FILE * const stream){// if (Array != NULL && stream != NULL)if (Array && stream){if (stream == stdout){// if(Array->kind == 1)if (Array->kind)printf("\n最大堆\n");// if(Array->kind == 0)elseprintf("\n最小堆\n");}ElemNumb index;for (index = 0; index < Array->size; ++index){if (stream == stdout)printf("%#x\t", (unsigned int)&Array->base[index].KeyValue);fprintf(stream, "%d\n", Array->base[index].KeyValue); // 此处随元素属性而改变}if (stream == stdout)printf("当前共有%d个元素\n", Array->size);}// if (Array == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}void AddHeadListByArray(ArrayList * const Array, const ArrayItem * const NewItem){// if (Array != NULL && NewItem != NULL)if (Array && NewItem){if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{// if (Array->size != 0)if (Array->size){ArrayItem *p;ArrayItem *q = &(Array->base[0]); // q为插入位置for (p = &(Array->base[Array->size - 1]); p >= q; --p) // 插入位置及之后的元素右移*(p + 1) = *p;*q = *NewItem; // 插入NewItem}// if (Array->size == 0)else(Array->base)[0] = *NewItem;++(Array->size); // 表长增1}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FullArray, NULL);}// if (Array == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}void AddTailListByArray(ArrayList * const Array, const ArrayItem * const NewItem){// if (Array != NULL && NewItem != NULL)if (Array && NewItem){ElemNumb order = Array->size;if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{(Array->base)[order] = *NewItem;++(Array->size); // 表长增1}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FullArray, NULL);}// if (Array == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}// 在顺序表Array插入新元素NewItem作为第order个位置// 1 ≤ order ≤ Array->size + 1void AddListByArray(ArrayList * const Array, const ElemNumb order, const ArrayItem * const NewItem){// if (Array != NULL && NewItem != NULL)if (Array && NewItem){if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{if ((order <= (Array->size + 1)) && (order > 0)){if (order <= Array->size) // 插入位置非表尾{ArrayItem *p;ArrayItem *q = &(Array->base[order - 1]); // q为插入位置for (p = &(Array->base[Array->size - 1]); p >= q; --p)// 插入位置及之后的元素右移*(p + 1) = *p;*q = *NewItem; // 插入NewItem}// if (order == (Array->size + 1))else // 插入位置为表尾(Array->base)[order - 1] = *NewItem;++(Array->size); // 表长增1}// if ((order > (Array->size + 1)) || (order < 0))elseUnusualToExit(InsertError, NULL);}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FullArray, NULL);}// if (Array == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}void DelHeadListByArray(ArrayList * const Array, ArrayItem * const DelItem){// if (Array != NULL && DelItem != NULL)if (Array && DelItem){// if (Array->size != 0)if (Array->size) // 顺序表非空{*DelItem = Array->base[0];if (Array->size != 1){ArrayItem *p, *q;p = &(Array->base[0]); // p为被删除元素的位置q = &(Array->base[Array->size]); // 表尾元素的位置for (++p; p < q; ++p) // 被删除元素之后的元素左移 *(p - 1) = *p;}--(Array->size); // 表长减1}// if (Array->size == 0)else // 顺序表为空UnusualToExit(EmptyArray, NULL);}// if (Array == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}void DelTailListByArray(ArrayList * const Array, ArrayItem * const DelItem){// if (Array != NULL && DelItem != NULL)if (Array && DelItem){ElemNumb order = Array->size - 1;// if (Array->size != 0)if (Array->size) // 顺序表非空{*DelItem = Array->base[order];if (Array->size != 1){ArrayItem *p, *q;p = &(Array->base[order]); // p为被删除元素的位置q = &(Array->base[Array->size]); // 表尾元素的位置for (++p; p < q; ++p) // 被删除元素之后的元素左移 *(p - 1) = *p;}--(Array->size); // 表长减1}// if (Array->size == 0)else // 顺序表为空UnusualToExit(EmptyArray, NULL);}// if (Array == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}// 在顺序表Array中删除第order个元素// 1 ≤ order ≤ Array->sizevoid DelOrderListByArray(ArrayList * const Array, const ElemNumb order, ArrayItem * const DelItem){// if (Array != NULL && DelItem != NULL)if (Array && DelItem){// if (Array->size != 0)if (Array->size) // 顺序表非空{if ((order <= Array->size) && (order >= 1)){*DelItem = Array->base[order - 1];if (Array->size != 1){ArrayItem *p, *q;p = &(Array->base[order - 1]);// p为被删除元素的位置q = &(Array->base[Array->size]); // 表尾元素的位置for (++p; p < q; ++p) // 被删除元素之后的元素左移 *(p - 1) = *p;}--(Array->size); // 表长减1}// if ((order > Array->size) || (order < 1))elseUnusualToExit(InsertError, NULL);}// if (Array->size == 0)else // 顺序表为空UnusualToExit(EmptyArray, NULL);}// if (Array == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}ElemNumb SearchListByArray(const ArrayList * const Array, const Key SearchKey){// if (Array != NULL)if (Array){ElemNumb i;for (i = 0; i < Array->size; ++i)if (Array->base[i].KeyValue == SearchKey)return i;return ImpossibleValue;}// if (Array == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 在顺序表Array中删除指定值的元素void DelSearchListByArray(ArrayList * const Array, const Key DelKey){// if (Array != NULL)if (Array){// if (Array->size != 0)if (Array->size){ElemNumb i;for (i = 0; i < Array->size; ++i)if (Array->base[i].KeyValue == DelKey){if (Array->size != 1){ArrayItem *p, *q;p = &(Array->base[i]);// p为被删除元素的位置q = &(Array->base[Array->size]); // 表尾元素的位置for (++p; p < q; ++p) // 被删除元素之后的元素左移 *(p - 1) = *p;}--(Array->size); // 表长减1return; // 若数组中有重复的指定元素值删除本行}}// if (Array->size == 0)elseUnusualToExit(EmptyArray, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void EnQueueByArray(ArrayList * const Array, ArrayItem *NewItem){AddTailListByArray(Array, NewItem);}void DeQueueByArray(ArrayList * const Array, ArrayItem *DelItem){DelHeadListByArray(Array, DelItem);}void PushByArray(ArrayList * const Array, ArrayItem * const NewItem){AddTailListByArray(Array, NewItem);}void PopByArray(ArrayList * const Array, ArrayItem * const DelItem){DelTailListByArray(Array, DelItem);}void GetTopOfStackByArray(const ArrayList * const Array, ArrayItem * const TopItem){// if (Array != NULL && TopItem != NULL)if (Array && TopItem){// if (Array->size != 0)if (Array->size)*TopItem = Array->base[Array->size - 1];// if (Array->size == 0)elseUnusualToExit(EmptyArray, NULL);}// if (Array == NULL || TopItem == NULL)elseUnusualToExit(NullPointer, NULL);}

// main.c// 本文件为顺序表接口测试程序 仅供参考#include "ArrayOfHeap.h"// ( ( 2 ^ ( sizeof ( ElemNumb ) * 8 - 1 ) ) - 1 )static const ElemNumb Max = (1 << ((sizeof(ElemNumb) << 3) - 1)) - 1;static const char * const FileName = "Heap.txt";int main(void){ArrayList Heap;const ArrayItem HeapElement[] = { { 8 },{ 7 },{ 6 },{ 5 },{ 4 },{ 3 },{ 2 },{ 1 } };const bool kind = 0; // 0为最小堆 1为最大堆CreateListByArray(&Heap, Max, kind, FileName);ElemNumb index;for (index = 0; index < sizeof(HeapElement) / sizeof(HeapElement[0]); ++index)AddTailListByArray(&Heap, &HeapElement[index]);AdjustHeap(&Heap); // 添加或删除堆元素后必须调用AdjustHeap调整堆元素OutputListByArrayToFile(&Heap);DestroyListByArray(&Heap);CreateListByArray(&Heap, Max, kind, FileName);InputListByArrayFromFile(&Heap);OutputListByArrayToMonitor(&Heap, stdout);DestroyListByArray(&Heap);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifreturn 0;}


0 0
原创粉丝点击