第九章 内部排序
排序:重点在于对于记录的关键字进行排序,得到按关键字有序记录序列
分为:
A.内部排序: 排序过程在内存中进行
B.外部排序: 待排序记录数据量过大,需要借助外部存储设备
排序的稳定性:排序后有相同关键字的记录顺序不变就是稳定的排序
插入类排序:
1.直接插入排序:将新加入的记录的关键字与之前的记录关键字从后往前比较,
若较小,则向前比较,同时进行比较的记录后移一个位置,直到找到小于等于的关键字,插入在其后.
实例代码如下:
void InsSort(int r[], int length){//r可以设置为结构数组,这里认为是数组 int i,j;for(i = 2; i < length; i++){ // i=2开始,i=1为第一个元素,认为是子表,i=0设置为监视哨 r[0] = r[i];//将待插入记录存到监视哨中,临时保存 j = i - 1; //i为初始待插入记录位置,i-1为需要比较的记录位置while(r[0] < r[j]){r[j+1] = r[j];j--;} r[j+1] = r[0];}
}
优点:算法简单,适用于记录数目较少且基本有序
时间复杂度:O(n^2).
2.折半插入排序:类似于快排
示例代码如下:
void BinSort(int r[], int length){int i, x, j;int low, high, mid;for(i = 2;i <= length; i++){x = r[i];low = 1;high = i - 1;while(low < high){//Attention!不取等,书上是错的 mid = (low + high) / 2;if(x < r[mid])high = mid - 1;elselow = mid + 1;}for(j = i - 1; j >= low; j--)r[j+1] = r[j];r[low] = x; }
}
时间复杂度:O(n^2).
需要比较的次数最大为其折半判定树的深度log2(n)
3.希尔排序:排序结果,基本有序;又称缩小增量排序;将关键字序列分为若干个子序列,对子序列插入排序
void f1(int r[], int length, int d){//d为这一轮子序列长度(增量) int i, j;for(i = 1+d; i <= length; i++){if(r[i] < r[i-d]){r[0] = r[i];for(j = i - d; j > 0 && r[j] > r[0]; j -= d){r[j + d] = r[j];}//如果子序列后者的记录关键字比前小,就复制前者到后者 r[j + d] = r[0];//复制要交换的一个到适合的位置 }}
} void f2(int r[], int length, int d[], int n){for(i = 0; i < n; i++)//d[]为增量数组,n为该数组长度 d[n-1] == 1; f1(r, length, d[i]);
}
时间复杂度:O(n^1.5).
算法不是稳定的 .
交换类排序:
1.冒泡排序(相邻比序法):反复扫描记录序列,依次交换逆序记录的位置
void BubbleSort(int r[], int n){bool change = true;int i,j;int x = 0;for(i = 1; i < n && change; i++){change = false;for(j = 1; j <= n - i; j++){if(r[j]>r[j+1]){x = r[j];r[j] = r[j+1];r[j+1] = x;change = true;}}}
} //下面这种简单些:上升法,不带标记
void BubbleSort(int r[], int n){int i, j, k;for(i = 0; i < n; i++){for(j = n - 2; j >= i; j--){if(r[j] > r[j+1]){k = r[j];r[j] = r[j+1];r[j+1] = k;}}}
}时间的复杂度:O(n^2).
2.快排:原理:一次性可以消除多个逆序来减少耗费时间
找到一个划分元,关键字小的移到前面,大的移到后面,递归在子序列中找出划分元.直到子表长度小于等于1
void QKSort(int r[], int low. int high){if(low < high){pos = QKPass(r, low, high);//再次快排QKSort(r, low, pos -1);QKSort(r, pos +1, high); }
} 一趟快速排序算法:
int QKPass(int r[], int low, int high){int x;while(low < high){while(low < high && r[high] > x)high--;if(low < high){r[low] = r[high];low++;} while(low < high && r[low] < x)low++;if(low < high){r[high] = r[low];high--;} }r[low] = x;return low;
}
时间复杂度:O(nlog2(n))