//SelectionSort.h
#ifndef _SELECTIONSORT_H_ #define _SELECTIONSORT_H_ #include <stdlib.h> #include <stdio.h> #include <time.h> #define SIZE 15 typedef int Element; typedef Element ListType[SIZE]; void CreateRandom(ListType List, int n); void print(ListType List, int n); //简单选择排序 void SimpleSort(ListType List, int n); //堆排序 void HeapSort(ListType List, int n); #endif //_SELECTIONSORT_H_ //SelectionSort.c #include "SelectionSort.h" void CreateRandom(ListType List, int n) { int i = 0; srand((unsigned)time(NULL)); for(i = 0; i < n; ++i) { List[i] = rand() % 0x7F; } } void print(ListType List, int n) { int i = 0; for(i = 0; i < n; ++i) { printf("%d\t", List[i]); } printf("\n"); } static void Swap(Element *a, Element *b) { Element Temp = *b; *b = *a; *a = Temp; } /********************************************************* 首先选定一个位置作为最小元素的下标位置,从此位置以外寻找比此位置 存在更小元素的位置,一趟下来最小的元素的位置就位于了数组的最左端, 第二趟下来,第二小的就在了数组的左端第二个位置............. 全部n-1趟下来排序完成 *********************************************************/ void SimpleSort(ListType List, int n) { int i = 0, j = 0, MiniPos = 0; for(i = 0; i < n-1; ++i) { MiniPos = i; //选定i为最小值 for(j = i+1; j < n; ++j) //寻找最小元素所在的位置 { if (List[MiniPos] > List[j]) { MiniPos = j; } } if( i != MiniPos ) //找到了更小元素所在位置 Swap(&List[i], &List[MiniPos]); } } /*************************************************************** 堆排序是利用堆的特点:堆顶元素一定是极值(极大值或是极小值)的特点, 每次取堆顶元素,然后再将剩下的元素再一次组成一个堆,再次取堆顶元 素,如此循环直到堆顶无元素则排序完成。 堆的定义:将堆看作一颗完全二叉树,并且用一个一位数组存储这个完全 二叉树,则有完全二叉树上任意一个非叶子节点的值均不大于(或不小于) 其左、右孩子的值 大项堆:完全二叉树上任意一个非叶子节点的值不小于其左、右孩子的值 小项堆:完全二叉树上任意一个非叶子节点的值不大于其左、右孩子的值 升序排序:使用大项堆(因为每次取得的极值是数组中最末一个元素,且 最末元素是由堆顶的极值交换而来) 降序排序:使用小项堆 ***************************************************************/ static void Adjust(ListType List, int pos, int n) //调整为大项堆 { int Child = 0, Parent = 0; Element Temp = List[pos]; //保存待调整节点值,以备交换 Parent = pos; Child = 2 * Parent + 1; //使Child指向Parent的左孩子 while (Child < n) //存在左孩子则循环向下调整,值大的节点向上移动,值小的节点下沉,以满足堆定义 { if( Child + 1 < n && List[Child + 1] > List[Child] ) //存在右孩子且右孩子的值更大 Child++; //使Child指向右孩子 if( Temp >= List[Child] ) //父节点已经大于存在的孩子节点(注意不能是List[Parent] > List[Child],除非使用的是方式是直接交换父子节点) break; //能到此处说明父节点必然小于存在的孩子节点 List[Parent] = List[Child]; //用孩子节点替换父节点,使这个非叶子节点不小于其存在的孩子 Parent = Child; //继续向下调整 Child = 2 * Parent + 1; } List[Parent] = Temp; //在叶子节点上恢复 } void HeapSort(ListType List, int n) { int pos = 0, i = 0; Element Temp; if( n <= 1 ) return ; pos = (n - 1) / 2; //从最后一个非叶子节点开始向上调整 while (pos >= 0) //创建堆 { Adjust(List, pos, n); pos--; } for(i = 0; i < n; ++i) //循环取堆顶元素到数组无序部分末位置,以对数组进行排序 { Temp = List[0]; //保存堆顶元素 List[0] = List[n - i -1]; //使用当前次的末尾元素覆盖堆顶元素 List[n - i - 1] = Temp; //将堆顶元素放在末尾 Adjust(List, 0, n - i - 1); //使用剩下的元素再次组成堆 } }main.c #include "SelectionSort.h" int main(int argc, char **argv) { ListType List ={ 0 }; int n = sizeof(List) / sizeof(Element); CreateRandom(List, n); printf("排序前\n"); print(List, n); //SimpleSort(List, n); HeapSort(List, n); printf("排序后\n"); print(List, n); system("pause"); return 0; }