针对408中考研基础专业课中的排序算法进行学习。
在学习的过程中不断思索,在目前学习的目标与过程中,抽象的元素有哪些?具体的元素有哪些?抽象的部份必须彻底吸收,具体的部份则当作经验,而累积的经验在将来归类整理之后,最终也将化为抽象。
排序算法分为内部排序和外部排序。
内部排序,针对于数据量相对较小。数据能全都在内存中的排序算法。这类算法要求时间复杂性低,空间复杂性可以高。
外部排序,针对存储在硬盘中的数据,这样的数据量大,内存一次放不下。对时间复杂性要求不高。对空间复杂性要求高。
设原序列 Ri = Rj ,i
大致分为五大类,插入排序、交换排序、选择排序、归并排序和基数排序
从内部算法工作量上,可以分为三类
通常,在排序过程中需进行两项基本的操作
前一个操作对大多数排序算法来说都是必要的,而后一个操作可以通过改变记录的存储方式予以避免。
带排列的记录序列可能有以下三种存储方式。
在这种存储方式中,记录之间的次序关系由其存储位置决定,则实现排序必须借助移动记录。
实现排序不需要移动记录,仅需修改指针即可。
在排序过程中不移动记录本身,而是移动地址向量这些记录的“地址”,在排序结束之后再按照地址向量中的值调整记录的存储位置。
第二种存储方式下实现的排序有称(链)表排序。第三种存储方式下实现的排序叫地址排序。
直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录增1的有序表。
void InsertSort(SqList &L){
// 对顺序表L作直接插入排序
for(i = 2; i<= L.length; ++i)
if(LT(L.r[i].key, L.r[i-1].key)){ // “<”,需将L.r[i]插入有序子表
L.r[0] = L.r[i]; // 负责为哨兵
L.r[i] = L.r[i-1];
for(j = i-2; LT(L.r[0].key, L.r[j].key); ++j)
L.r[j+1] = L.r[j]; // 记录后移
L.r[j+1] = L.r[0]; // 插入到正确位置
}
} // InsertSort
折半插入排序
希尔排序
void ShellSort(ElemType A[], int n){
// A[0]是暂存单元,不是哨兵,当j < 0时插入位置已到
for(dk = n/2, dk>=1;dk=dk/2) // 步长变化
for(i = dk+1; i<n;++1)
}
以交换进行排序的方法。最简单的就是冒泡排序。
快速排序(Quick Sort)是对气泡排序的一种改进,它的基本思想是,通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序。
快速排序的思想是基于分治法的:在待排序表L[1…n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+1…n],使得L[1…k-1]中所有元素小于pivot,L[k+1…n]中所有元素大于等于pivot,则pivot放在了其最终位置L[K]上,这个过程为一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直到每部分内只有一个元素或为空为止,即所有元素放在了其最终位置上。
void QuickSort(ElemType A[ ], int low, int high){
if(low < high){ // 跳出递归的条件
// partition() 划分操作,将表[LOW..HIGH]划分为满足上述条件的两个子表
int pivotpos = partition(A, low, high); // 划分
QuickSort(A, low, pivotpos-1); // 对两个子序列递归。
QuickSort(A, pivotpos, high);
}
}
int Partition(ElemType A[], int low, int high){ // 一趟划分
ElemType pivot = A[low]; // 将当前表中第一个元素设为枢轴,对表进行划分
while(low < high){ // 循环跳出条件
while(low<high && A[high] >= pivot) --high;
A[low] = A[high]; // 将比枢轴小的元素移动到左端
while(low<high && A[low] <= pivot) ++low;
A[high] = A[low]; // 将比枢轴大的元素移动到右端
}
A[low] = pivot; // 枢轴元素放到最终位置
return low; // 返回枢轴元素的最终位置
}
选一个最大(最小)放在前面,或后面。
转载地址:https://www.cnblogs.com/lanhaicode/p/11284230.html
// 归并排序 将序列二分到1,然后递归合并
void MergeSort_UptoDowm(int* num, int start, int end){
int mid = start +(end - start)/2;
if(start >= end) return ;
MergeSort_UptoDowm(num, start, mid); // 拆分
MergeSort_UptoDowm(num, mid+1, end); // 拆分
merge(num, start, mid, end); // 合并
}
void Merge(int *num, int start, int mid, int end){
int *temp = (int *)malloc(sizof(int)*(end - start+1));
// 申请空间来存放两个有序区归并后的临时区域
int i = start;
int j = mid+i;
int k = 0;
while(i <=mid && j<=end){ // 从小到大放入 堆区
if(num[i] <=num[j]){
temp[k++] = num[i++];
}
else{
temp[k++] = num[j++];
}
}
while(i <= mid){ // 后面剩余的 放入堆区
temp[k++] = num[i++];
}
while(j < =end){
temp[k++] = num[j++];
}
// 将临时区域中排序后的元素,整合到原数组中
for(i = 0;i < k; i++)
{
num[start+i] = temp[i];
}
free(temp);
}
红色