算法导论--堆排序

以前写过一个堆排序,但是实话实说,根本不知所云。

今天看了算法导论 关于堆排序的讲解,就实现了一下。

在《算法导论》中关于堆排序的描述是:像合并排序而不像插入排序,运行时间为O(n*logn)。
是一种原地排序算法:在任何时间只有常数个数据在数组外面。

堆排序操作的重要伪代码:

1:保持堆的性质;
MAX-HEAPIFY(A,i)
1 l <- LEFT(i)
2 r <- RIGHT(i)
3 if l<=heap-size(A) and A[l] > A[i]
4     then largest <- l
5     else largest <- i
6 if r<=heap-size(A) and A[r] > A[i]
7    then largest <- r
8 if largest != i
9        then exchange A[i]<->A[largest]
10 MAX-HEAPIFY(A,largest)

2:建堆
BUILD-MAX-HEAP(A)
1  heap-size[A] <- length[A]
2  for i <- length[A]/2 downto 1
3        do MAX-HEAPIFY(A,i)

3:排序
HEAP-SORT(A)
1 BUILD-MAX-HEAP(A)
2 for i <- length[A] downto 2
3    do exchange A[1] <-> A[i]
4        heap-size[A] <- heap-size[A]-1
5        MAX-HEAPIFY(A,1)

算法导论中讲解的是最大堆,我实现的是最小堆,其实两者的操作区别不大:

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
int length;

int parent(int i)
{
	return i/2;
}
int left(int i)
{
	return 2*i;
}
int right(i)
{
	return 2*i+1;
}


void swap(int *group,int i,int k)
{
	int temp;
	temp = group[i];
	group[i]=group[k];
	group[k]=temp;
}

//调整堆
void heap_adjust(int group[],int i)
{
	int l,r,smallest;
	l = left(i);
	r = right(i);

	if(l<=length && group[l]<group[i])
		smallest = l;
	else
		smallest = i;

	if(r<=length && group[r]<group[smallest])
		smallest = r;
	if(smallest != i)
	swap(group,i,smallest);
}

//建立一个堆
void build_heap(int group[])
{
	int i;
	for(i=length/2;i>=1;i--)
	{
		heap_adjust(group,i);
	}
}

//输出堆中最小的元素
int heap_min(int group[])
{
	int min;
	if(length<1)return FALSE;
	min = group[1];
	group[1]=group[length];
	length-=1;
	heap_adjust(group,1);
	return min;
}

//增加堆中某一元素的数值,注意是增加
void heap_increase(int group[],int i,int key)
{
	if(key < group[i])return ;
	else
	{
		group[i]=key;
		while(i>1&&group[parent(i)]<group[i])
		{
			swap(group,i,parent(i));
			i=parent(i);
		}
	}
}

//向堆中添加元素
void heap_insert(int group[],int key)
{
	length += 1;
	group[length] = -999999;
	heap_increase(group,length,key);
}

//堆排序
void heap_sort(int *group)
{
	int i;
	build_heap(group);
	for(i=length;i>=2;i--)
	{
		swap(group,1,i);
		length--;
		heap_adjust(group,1);
	}
}
int main()
{
	int *group;
	int i,n;
	scanf("%d",&n);
	group = (int*)malloc(sizeof(int)*(2*n+1));
	for(i=1;i<=n;i++)
		scanf("%d",group+i);
	length = n;
	heap_sort(group);
	for(i=1;i<=n;i++)
		printf("%d ",*(group+i));
	return 0;
}


#include <stdio.h> #include <stdlib.h> // 最小堆结构体 typedef struct MinHeap { int* data; // 存储堆元素的数组 int size; // 当前堆的大小 int capacity;// 堆的最大容量 } MinHeap; // 初始化最小堆 MinHeap* createMinHeap(int capacity) { MinHeap* heap = (MinHeap*)malloc(sizeof(MinHeap)); heap->capacity = capacity; heap->size = 0; heap->data = (int*)malloc((capacity + 1) * sizeof(int)); // 1-based索引 return heap; } // 交换两个整数 void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 向上调整堆(插入元素时) void heapifyUp(MinHeap* heap, int index) { while (index > 1 && heap->data[index] < heap->data[index / 2]) { swap(&heap->data[index], &heap->data[index / 2]); index /= 2; } } // 向下调整堆(删除元素时) void heapifyDown(MinHeap* heap, int index) { int smallest = index; int left = 2 * index; int right = 2 * index + 1; if (left <= heap->size && heap->data[left] < heap->data[smallest]) smallest = left; if (right <= heap->size && heap->data[right] < heap->data[smallest]) smallest = right; if (smallest != index) { swap(&heap->data[index], &heap->data[smallest]); heapifyDown(heap, smallest); } } // 插入元素到堆 void insert(MinHeap* heap, int value) { if (heap->size >= heap->capacity) { // 扩容(可选,本题数据量固定,可省略) heap->capacity *= 2; heap->data = (int*)realloc(heap->data, (heap->capacity + 1) * sizeof(int)); } heap->data[++heap->size] = value; heapifyUp(heap, heap->size); } // 提取堆顶最小元素 int extractMin(MinHeap* heap) { if (heap->size == 0) return -1; // 空堆 int min = heap->data[1]; heap->data[1] = heap->data[heap->size--]; heapifyDown(heap, 1); return min; } // 销毁堆 void destroyMinHeap(MinHeap* heap) { free(heap->data); free(heap); } int main() { int n; scanf("%d", &n); MinHeap* heap = createMinHeap(n); for (int i = 0; i < n; i++) { int num; scanf("%d", &num); insert(heap, num); } int total体力 = 0; while (heap->size > 1) { // 提取两个最小元素 int a = extractMin(heap); int b = extractMin(heap); // 合并 int sum = a + b; total体力 += sum; // 插入合并后的元素 insert(heap, sum); } printf("%d\n", total体力); destroyMinHeap(heap); return 0; }帮我简洁优化一下
最新发布
11-27
以下是对原代码进一步简洁优化后的 C 语言实现,包含最小堆结构体、初始化、插入、提取最小元素等功能: ```c #include <stdio.h> #include <stdlib.h> // 最小堆结构体 typedef struct { int *data; int size; int capacity; } MinHeap; // 交换两个整数 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 初始化最小堆 MinHeap* initHeap(int capacity) { MinHeap *heap = (MinHeap*)malloc(sizeof(MinHeap)); heap->data = (int*)malloc(capacity * sizeof(int)); heap->size = 0; heap->capacity = capacity; return heap; } // 上滤操作 void siftUp(MinHeap *heap, int index) { while (index > 0 && heap->data[index] < heap->data[(index - 1) / 2]) { swap(&heap->data[index], &heap->data[(index - 1) / 2]); index = (index - 1) / 2; } } // 插入元素到最小堆 void insert(MinHeap *heap, int value) { if (heap->size < heap->capacity) { heap->data[heap->size] = value; siftUp(heap, heap->size++); } } // 下滤操作 void siftDown(MinHeap *heap, int index) { int left, right, smallest; while (1) { left = 2 * index + 1; right = 2 * index + 2; smallest = index; if (left < heap->size && heap->data[left] < heap->data[smallest]) smallest = left; if (right < heap->size && heap->data[right] < heap->data[smallest]) smallest = right; if (smallest == index) break; swap(&heap->data[index], &heap->data[smallest]); index = smallest; } } // 提取最小元素 int extractMin(MinHeap *heap) { if (heap->size == 0) return -1; int min = heap->data[0]; heap->data[0] = heap->data[--heap->size]; siftDown(heap, 0); return min; } // 销毁最小堆 void destroyHeap(MinHeap *heap) { free(heap->data); free(heap); } int main() { MinHeap *heap = initHeap(10); insert(heap, 3); insert(heap, 1); insert(heap, 2); printf("Extracted Min: %d\n", extractMin(heap)); printf("Extracted Min: %d\n", extractMin(heap)); destroyHeap(heap); return 0; } ``` ### 优化点说明 - 移除了不必要的注释和复杂逻辑,使代码更加简洁。 - 函数命名更加简洁,如 `initMinHeap` 改为 `initHeap`,`freeMinHeap` 改为 `destroyHeap` 等。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值