算法导论 第6章 堆排序(简单选择排序、堆排序)

来源:互联网 发布:淘宝运动鞋店铺 编辑:程序博客网 时间:2024/06/05 22:40

堆数据结构实际上是一种数组对象,是以数组的形式存储的,但是它可以被视为一颗完全二叉树,因此又叫二叉堆。堆分为以下两种类型:

大顶堆:父结点的值不小于其子结点的值,堆顶元素最大

小顶堆:父结点的值不大于其子结点的值,堆顶元素最小

堆排序的时间复杂度跟合并排序一样,都是O(nlgn),但是合并排序不是原地排序(原地排序:在排序过程中,只有常数个元素是保存在数组以外的空间),合并排序的所有元素都被拷贝到另外的数组空间中去,而堆排序是一个原地排序算法。

1、在堆排序中,我们通常使用大顶堆来实现,由于堆在操作上是被看着一颗完全二叉树,所以其高度为lgn,堆结构上的一些操作的时间复杂度也通常是O(lgn)。


/* *算法导论 第六章 堆排序 *堆数据结构的实际存储是作为一个顺序数组来保存的 *对堆的操作是将它作为一个完全二叉树的结构来使用的 * *堆排序也是属于一种选择排序,不过相比简单选择排序(时间复杂度为O(n^2)),堆排序要快得多 *堆排序分为以下几个步骤: *首先是建立大顶堆,即函数buildMaxHeap,建堆实际上是利用堆的最大化调整(maxHeapify)自底向上来实现的 *然后是逐步将堆顶的最大元素交换到堆的结尾,堆的大小也不断缩小,然后再将堆最大化,从而实现排序 * *其中建堆的时间复杂度为O(n),堆的最大化调整时间复杂度为O(lgn),所以总的 *时间复杂度是O(n*lgn+n),即O(nlgn) */#include <iostream>using namespace std;void printArray(int arr[], int len);void heapSort(int arr[], int len);void maxHeapify(int arr[], int heapSize, int pos);void buildMaxHeap(int arr[], int len);void selectSort(int *arr, int len);void exchange(int arr[], int i, int j);int main(){int arr[] = {16, 14, 10, 8, 7, 9, 3, 2, 4, 1};int len = sizeof(arr) / sizeof(arr[0]);cout << "原数组:" << endl;printArray(arr, len);heapSort(arr, len);//selectSort(arr, len);cout << "排序后的数组:" << endl;printArray(arr, len);return 0;}void printArray(int arr[], int len){for (int i=0; i<len; i++){cout << arr[i] << " ";}cout << endl;}void heapSort(int arr[], int len){buildMaxHeap(arr, len);for (int i=len-1; i>0; i--){int temp = arr[0];arr[0] = arr[i];arr[i] = temp;maxHeapify(arr, i, 0);}}void maxHeapify(int arr[], int heapSize, int pos){int lPos = (pos + 1) * 2 - 1;int rPos = (pos + 1) * 2;int largest = pos;if (lPos < heapSize && arr[lPos] > arr[largest])largest = lPos;if (rPos < heapSize && arr[rPos] > arr[largest])largest = rPos;if (largest != pos){int temp = arr[pos];arr[pos] = arr[largest];arr[largest] = temp;maxHeapify(arr, heapSize, largest);}}void buildMaxHeap(int arr[], int len){for (int i=len/2-1; i>=0; i--){maxHeapify(arr, len, i);}}/* *简单选择排序 *每次经过 n-i 次比较,从序列中选出i之后的最小元素放在第 i 个位置,以此排序 *时间复杂度为O(n^2) */void selectSort(int *arr, int len){for (int i=0; i<len; i++){int minIndex = i;for (int j=i+1; j<len; j++){if (arr[j] < arr[minIndex])minIndex = j;}if (minIndex != i){exchange(arr, i, minIndex);}}}void exchange(int arr[], int i, int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}


2、堆结构可以用来实现优先级队列,优先级队列是一组元素构成的集合,可以从中取出最大或者最小的元素,堆是优先级队列的一种很好的实现。通过堆,优先级队列上的任意操作可以再O(lgn)时间内实现。


3、习题6.5-8解答

/* *算法导论 第六章 习题6.5-8 * *将k个链表中的首元素取出来作为一个数组,构成一个最小堆,堆顶元素即为最小 *每次将堆顶元素插入到新链表尾部,然后将该元素原来所在链表的下一元素取出放到堆顶 *若该链表取完了,则直接将堆尾元素放到堆顶,并将堆的大小减1,调整堆,重复取出堆顶 *最小元素插入到新链表,直到k个链表都为空了为止 * *时间复杂度分析:建堆为O(k),取出堆中最小元素为O(lgk),共取了n次 *时间复杂度为O(k+nlgk)=O(nlgk) */#include <iostream>using namespace std;typedef struct LinkNode {int key;LinkNode *next;} LinkNode;LinkNode* createLink(int arr[], int len);LinkNode* heapExtractMin(LinkNode* arr[], int &len);void minHeapify(LinkNode* arr[], int heapSize, int pos);void buildMinHeap(LinkNode* arr[], int len);int main(){int k = 5, n = 20;int arr1[3] = {11, 14, 67};int arr2[2] = {5, 35};int arr3[5] = {3, 8, 12, 25, 90};int arr4[4] = {9, 21, 49, 73};int arr5[6] = {1, 32, 33, 45, 53, 88};LinkNode *link1 = createLink(arr1, 3);LinkNode *link2 = createLink(arr2, 2);LinkNode *link3 = createLink(arr3, 5);LinkNode *link4 = createLink(arr4, 4);LinkNode *link5 = createLink(arr5, 6);/* *把堆定义成一个指针数组,需要注意指针数组与数组指针的区别 *指针数组:定义的是一个数组,数组中的每一个元素都是一个指针 *数组指针:定义的是一个指针,这个指针指向一个数组 *///定义堆数组LinkNode* heap[] = {link1, link2, link3, link4, link5};buildMinHeap(heap, k);//定义重新排序后的链表LinkNode *resultLink = heapExtractMin(heap, k);LinkNode *beforeNode = resultLink;while (beforeNode && n-- > 1){LinkNode *node = heapExtractMin(heap, k);beforeNode->next = node;beforeNode = node;}while (resultLink){cout << resultLink->key << " ";LinkNode *node = resultLink;resultLink = resultLink->next;delete node;}cout << endl;return 0;}LinkNode* createLink(int arr[], int len){LinkNode *nextNode = NULL;for (int i=len-1; i>=0; i--){LinkNode *node = new LinkNode();node->key = arr[i];node->next = nextNode;nextNode = node;}return nextNode;}LinkNode* heapExtractMin(LinkNode* arr[], int &len){if (len < 1)return NULL;LinkNode *minNode = arr[0];if (arr[0]->next){arr[0] = arr[0]->next;} else {len--;arr[0] = arr[len];}if (len > 1){minHeapify(arr, len, 0);}return minNode;}void minHeapify(LinkNode* arr[], int heapSize, int pos){int lPos = (pos + 1) * 2 - 1;int rPos = (pos + 1) * 2;int smallest = pos;if (lPos < heapSize && arr[lPos]->key < arr[smallest]->key)smallest = lPos;if (rPos < heapSize && arr[rPos]->key < arr[smallest]->key)smallest = rPos;if (smallest != pos){LinkNode* temp = arr[pos];arr[pos] = arr[smallest];arr[smallest] = temp;minHeapify(arr, heapSize, smallest);}}void buildMinHeap(LinkNode* arr[], int len){for (int i=len/2-1; i>=0; i--){minHeapify(arr, len, i);}}

4 0
原创粉丝点击