1.排序分为内部排序和外部排序
内部排序:整个排序过程都在内存中进行
外部排序:由于排序的数据量大,需要依靠外部内存才能完成排序
2.排序的稳定性
在排序的过程中存在多个相同的关键字的纪录,若排序前关键字顺序和排序后关键字顺序一致,则称这种排序方法是稳定的,反之则不稳定。
3.内部排序分类:(1)插入类排序 :在一个已排序好纪录子集基础上,每一步将下一个待排序的纪录有序插入到已经排好序的子集中,直到将所有待排序的纪录全部插入为止
在此算法思想上,插入排序又可以分为:直接插入排序,折半插入排序,希尔排序
直接插入排序是一种最基本的插入排序,基本思想是将第i个纪录插入到前面i-1个已经拍好序的纪录中,直接插入排序是从i=2开始的,默认是将第一个纪录视为已拍好序的单元子集合,
typedef int KeyType; typedef struct { KeyType key; int data; }RecordType;
//直接插入排序 void InsSort(RecordType r[],int length){ for (int i = 2; i <= length; i++) { r[0] = r[i];int j = i - 1;//r[0] 备份待插入纪录 while (r[0].key < r[j].key) {//与前面子集进行比对,如果小就将原来的数后移 r[j+1] = r[j]; j = j-1; } r[j+1] = r[0]; } }
折半插入排序:由于直接插入排序没有每次都要和前面的数进行一次比较,没有利用数据有序性这一特点,折半插入排序正是为了解决这一点,主要分为两步,第一步是查找插入点,第二步这是移动元素进行插入
void BinSort(RecordType r[],int length,RecordType e){ int low = 0; int high = length-1; while (low <= high) { int middle = (low + high)/2; if (e.data < r[middle].data) { high = middle - 1; } if (e.data > r[middle].data) { low = middle + 1; } } for (int i = low; i<length; i++) { r[i+1] = r[i]; } r[low] = e; }希尔排序:是冒泡排序的增强版,通过设定一个增量数组,每次对排列的数组进行分组,分组数月来越小,直至为1,这时算法退化为冒泡排序
/*一趟希尔排序*/ void ShellInsert(RecordType r[], int length,int delta){ for (int i = 1+delta; i < length; i++) { if (r[i].key < r[i-delta].key) { r[0] = r[i]; int j; for (j = i - delta; j >0&&r[0].key < r[j].key; j -= delta) { r[j+delta] = r[j]; } r[j+delta] = r[0]; } } } void ShellSort(RecordType r[],int length,int delta[],int n){ /*对纪录数组r做希尔排序,length为数组r的长度,delta为增量数组,n为delta数组的长度*/ for (int i = 0; i <= n-1; ++i) { ShellInsert(r, length, delta[i]); } }
快速排序:算法设定两个游标,前面一个后面一个,分别从两端向中间靠拢,前面游标将左边 比数组第一个数据大的筛到后面去,后面游标将比第一个数据小的筛到前面去,两个游标交叉进行,最后相遇相遇为止
int QKPass(RecordType r[],int left,int right){ RecordType x = r[left]; int low = left,high = right; while (low < high) { while (low < high && r[high].key >= x.key) { high -- ; } if (low < high) { r[low] = r[high]; low ++; } while (low < high && r[low].key < x.key) { low ++; } if (low < high) { r[high] = r[low]; ; high --; } } r[low] = x; return low; } void QKSort(RecordType r[],int low,int high){ if (low < high) { int pos = QKPass(r, low, high); QKSort(r, low, pos - 1); QKSort(r, pos+1, high); } }
冒泡排序:基本的交换类排序算法之一,通过比较相邻两个数大小交换位置,最后将最大的数据排到最后完成一次排序,下次排序将次大的数据排到倒数第二,依次下去,最后时限排好所有数据
void BubbleSort(RecordType r[],int length){ int n = length; bool change = true; for (int i = 1; i<=n-1 && change; i ++) { change = false; for (int j = 0;j <= n - i; ++ j) { //i表示需要排几次 if (r[j].key > r[j+1].key) {//j每一个i排序内做的交换 RecordType temp = r[j]; r[j] = r[j+1]; r[j+1] = temp; change = true; } } } }
简单选择排序:从数组第一个数开始,寻找数组中最小的数并将其插入,依次进行,最后实现排序
void SelectSort(RecordType r[],int length){ int n = length; for (int i = 0; i <= n-1; i++) { int k = i;//k为最小值下表 for (int j = i+1; j<=n-1; j++) { if (r[j].key <r[k].key) { k = j; } } if (k != i) { //最小值下标发生了改变 RecordType temp = r[i]; r[i] = r[k]; r[k] = temp; } } }堆排序:数据按照堆结构存储
//调整堆 void sift(RecordType r[],int k,int m){ RecordType t = r[k]; KeyType x = r[k].key; int i = k; int j = 2*i; bool finish = false; while (j <= m && !finish) { if (j < m && r[j].key < r[j+1].key) { j = j+1; } if (x > r[j].key) { finish = true; }else{ r[i] = r[j]; i = j; j = 2*i; } } r[i] = t; } //建初堆 void crt_heap(RecordType r[],int length){ int n = length; for (int i = n/2; i>=1; --i) { sift(r, i, n); } } void HeapSort(RecordType r[],int length){ crt_heap(r, length); int n = length; for (int i = n; i >= 2; --i) { RecordType b = r[1]; r[1] = r[i]; r[i] = b; sift(r, 1, i-1); } }
}