目录
1、二分查找:(折半查找)
二分查找的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。
二分查找仅适用于有序数据,二分查找仅适用于数组。小数据量下,线性查找性能更佳。当数据量 n 较小时,线性查找反而比二分查找更快。
int Binary_Search(SeqList L,Elem Type key){
int low = 0,high = L.length - 1,mid;
while(low <= high){
mid = (low + high)/2; //取中间位置
if(L.elem[mid] == key){
return mid; //查找成功返回所在位置
}else if{L.elem[mid] > key){
high = mid -1; //从前半部分继续查找
}else{
low = mid + 1; //从后半部分继续查找
}
}
return -1; //查找失败,返回-1
}
时间复杂度为O():在二分循环中,区间每轮缩小一半,因此循环次数为
。
空间复杂度为O(1):指针 i 和 j 使用常数大小空间。
2、直接选择排序 (不稳定)
时间复杂度为O()
空间复杂度为O(1)
void select_Sort(int A[],int N) /*选择排序*/
{
int i,j,k,temp;
for(i=1;i<N;i++){
k = i;
for(j=i+1;j<=N;j++){
if(A[k]>A[j]) k=j;
} //每次循环找出一个最小元素,A[k]
if(k!=i){
temp = A[k];
A[k] = A[i];
A[i] = temp;
} //交换A[k]和A[i]
}
}
3、冒泡排序:
两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。
/*冒泡排序*/
void bubbleSort(int nums[],int size){
//外循环:未排序区间为[0,i]
for(int i = size - 1;i > 0;i--){
//内循环:将未排序区间[0,i]中的最大元素交换至该区间的最右端
for(int j = 0;j < i;j++){
if(nums[j] > nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
}
/*冒泡排序(优化标志)*/
void bubbleSortWithFlag(int nums[],int size){
//外循环:未排序区间为[0,i]
for(int i = size - 1;i > 0;i--){
bool flag = false;
//内循环:将未排序区间[0,i]中的最大元素交换至该区间的最右端
for(int j = 0;j < i;j++){
if(nums[j] > nums[j+1]){
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
flag = true;
}
}
if(!flag)
break;
}
}
4、(直接)插入排序:(稳定)
/*插入排序*/
void insertionSort(int nums[],int size){
//外循环:已排序元素数量为1,2,...,n
for(int i = 1;i < size; i++){
int base = nums[i],j = i - 1;
//内循环:将base插入到已排序部分的正确位置
while(j >= 0 && nums[j] > base){
//将nums[j]向右移动一位
nums[j+1] = nums[j];
j--;
}
//将base赋值到正确位置
nums[j + 1] = base;
}
}
5、折半插入排序:
void BinInsertSort(RecType R[],int n)
{
int i, j, low, high, mid;
RecType tmp;
for (i=1;i<n;i++){
if(R[i].key<R[i-1].key) //反序时
tmp = R[i]; //将R[i]保存到tmp中
low = 0;
high = i-1;
while(low<=high){ //在R[low..high]中查找插入的位置
mid=(low+high)/2; //取中间位置
if(tmp.key<R[mid].key
high = mid - 1; //插入点在左半区
else
low = mid + 1; //插入点在右半区
} //找位置high+1
for(j=i-1;j>=high+1;j--) //记录后移
R[j+1] = R[j];
R[high+1] = tmp; //插入tmp
}
}
}
6、希尔插入排序:(不稳定)
void shell_Sort(int A[],int N,int d[],int t)
{
int i,j,k,h;
for(k=0;k<t;k++) /*进行t遍插入排序*/
{
h=d[k]; /*当前增量*/
for(i=h+1;i<=N;i++)
{
j=i-h;
A[0]=A[i]; /*步长为h*/
while(j>0&&A[0]<A[j]) /*找插入位置并后移*/
{
A[j+h]=A[j]; /*后移*/
j=j-h; /*继续向前(左)查找*/
}
A[j+h]=A[0];
}
}
}
7、快速排序:(不稳定)
int quickPass(int A[],int low,int high)
{
int i=low;j=high;
A[0]=A[i];
while(i<j){ /*来回比较法的一次划分*/
while(i<j&&A[j]>=A[0]) /*从右向左*/
j--;
if(i<j)
A[i++]=A[j];
while(i<j&&A[i]<A[0]) /*从左向右*/
i++;
if(i<j)
A[j--]=A[i];
}
A[i]=A[0]; /*i就是A[0]最终的位置*/
return i;
}
/* 快速排序类 */
// 快速排序类-哨兵划分
int partition(int nums[],int left,int right){
// 以 nums[left] 为基准数
int i = left,j = right;
while(i<j){
while(i<j && nums[j] >= nums[left]){
// 从右向左找首个小于基准数的元素
j--;
}
while(i<j && nums[i] <= nums[left]){
// 从左向右找首个大于基准数的元素
i++;
}
// 交换这两个元素
swap(nums, i, j);
}
// 将基准数交换至两子数组的分界线
swap(nums, i, left);
// 返回基准数的索引
return i;
}
// 快速排序类-快速排序
void quickSort(int nums[],int left,int right){
// 子数组长度为 1 时终止递归
if(left >= right){
return;
}
// 哨兵划分
int pivot = partition(nums,left,right);
// 递归左子数组、右子数组
quickSort(nums,left,pivot - 1);
quickSort(nums,pivot + 1;right);
}
8、堆排序:
void sift(RecType R[],int low,int high) //调整堆的算法
{
int i = low,j = 2*i; // R[j] 是 R[i] 的左孩子
RecType tmp = R[i];
while(j <= high)
{
if(j < high && R[j].key<R[j+1].key)
j++; // j 指向大孩子
if(tmp.key < R[j].key) // 双亲小
{
R[i]=R[j]; // 将R[j]调整到双亲结点位置
i = j; // 修改i和J值,以便继续向下筛选
j = 2*i;
}
else break; // 双亲大:不再调整
}
R[i] = tmp;
}
堆排序算法
void HeapSort(RecType R[],int n)
{
int i;
for(i=n/2;i>=1;i++) // 循环建立初始堆
sift(R,i,n);
for(i=n;i>=2;i--) // 进行n-1次循环,完成堆排序
{
swap(R[1],R[i]); // R[1]→R[i]
sift(R,1,i-1); // 筛选R[1]结点,得到i-1个结点的堆
}
}
9、归并排序:
void merge(int A[],int u,int m,int v)
{
int i,j,k,t,B[N+1];
i=u;j=m+1;k=u;
while(i<=m && j<=v)
if(A[i]<=A[j])
B[k++]=A[i++];
else
B[k++]=A[j++];
while(i<m)
B[k++]=A[i++];
while(i<v)
B[k++]=A[j++];
for(i=u;i<=v;i++)
A[i]=B[i];
}
void merge_Sort(int A[],int low,int high)
{
int mid;
if(low<high) /*序列元素个数超过2个*/
{
mid=(low+high)/2;
merge_Sort(A,low,mid); /*递归归并排序左段*/
merge_Sort(A,mid+1,high); /*递归归并排序右段*/
merge(A,low,mid,high); /*归并左右段*/
{
}
10、基数排序:
linklist RadixSort(linklist A)
{
linklist fr[R],re[R]; /*建立R个桶队列,分别记录队首和队尾*/
int i,j,K;
for(i=D-1;i>=0;i--){ /*从最低位关键字开始*/
for(j=0;j<R;j++)
fr[j] = re[j] = NULL; /*初始化*/
while(A){ /*将关键字逐一分配到桶*/
K=A->key[i]; /*取出当前关键字位*/
if(!fr[K]) fr[K] = A; /*放入空桶*/
else re[K]->next = A; /*否则放入桶尾*/
re[K]=A; /*更新尾指针*/
A=A->next;
}
for(j=R-1;i>=0;j--){
/*将所有桶中元素收集串起来*/
if(fr[j]){ /*桶非空*/
re[j]->next = A;
A = fr[j];
}
}
}
return A;
}