2023数据结构考研复习-排序
Posted ZSYL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2023数据结构考研复习-排序相关的知识,希望对你有一定的参考价值。
2023数据结构考研复习-排序(八)
十大排序算法Java版
插入排序
void InsertSort(int a[] ,int n)
int i, j;
for (i = 2; i <= n; i++) //依次将A[2]~A[n]插入前面已排序序列
if (a[i] < a[i-1]) //若A[i]关键码小于其前驱,将A[i]插入有序表
a[0] = a[i]; //复制为哨兵,A[0]不存放元素
for (j = i-1; a[0] < a[j]; j--) //从后往前查找待插入位置 A[j+1]-A[j];
a[j+1] = a[j]; //向后挪位
a[j+1] = a[0]; //复制到插入位置
折半插入排序
void InsertSort(int a[] ,int n)
int i, j;
for (i = 2; i <= n; i++) //依次将A[2]~A[n]插入前面已排序序列
if (a[i] < a[i-1]) //若A[i]关键码小于其前驱,将A[i]插入有序表
a[0] = a[i]; //复制为哨兵,A[0]不存放元素
int low = 1, high = i-1;
while (low <= high)
mid = (low + high) / 2;
if (a[mid] > a[0])
high = mid - 1;
else
low = mid+1;
for (j = i-1; j >= high + 1; j--) //从后往前查找待插入位置 A[j+1]-A[j];
a[j+1] = a[j]; //向后挪位
a[high+1] = a[0]; //复制到插入位置
希尔排序
void ShellSort (int a[], int n)
//步长变化
for (dk = n/2; dk >= 1; dk/=2)
for (i = dk+1; i <= n; i++)
if (a[i] < a[i-dk])
a[0] = a[i]; //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
for (j = i-dk; j > 0 && a[0] < a[j]; j-=dk)
a[j+dk] = a[j]; //记录后移,查找插入的位置
a[j+dk] = a[0]; //插入
冒泡排序
void BubbleSort (int a[], int n)
for (int i = 0; i < n-1; i++)
flag = false;
for (j = n - 1; j > i; j--)
if (a[j-1] > a[j])
swap(a[j-1], a[j]);
flag = true;
if (!flag)
return;
快速排序
void QuickSort (int a[], int low, int high)
if (low < high)
int pivotpos = Partition(A, low, high);
Partition(A, low, pivotpos-1);
Partition(A, pivotpos+1, high);
void QuickSort (int a[], int low, int high)
if (low < high)
int pivotpos = Partition(A, low, high);
Partition(A, low, pivotpos-1);
Partition(A, pivotpos+1, high);
int Partition(int[] a, int low, int high)
int 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; //返回存放枢轴的最终位置
选择排序
void selectsort(ElemType A[] ,int n)
for(i=0;i<n-1;i++) //一共进行n-1趟
min = i; //记录最小元素位置
for(j = i+1; j < n; j++)
if(A[j] < A[min]) min=j; //更新最小元紊位置
if(min!=i)
swap(A[i], A[min]); //封装的swap()函数共移动元素3次
堆排序
void BuildMaxHeap (ElemType A[],int len)
for(int i = len/2; i > 0; i--) //从i=[n/2]~1,反复调整堆
HeadAdjust(A, i, len);
void HeadAdjust (ElemType A[],int k, int len) //函数HeadAdjust将元素k为根的子树进行调整
A[0] = A[k]; //A[0]暂存子树的根结点
for(i = 2*k; i <= len; i *= 2) //沿key较大的子结点向下筛选
if(i<len && A[i] < A[i+1])
i++; //取key 较大的子结点的下标
if(A[0] >= A[i])
break; //筛选结束
else
A[k]=A[i]; //将A[i]调整到双亲结点上
k=i; //修改k值,以便继续向下筛选
A[k]=A[3]; //被缔选结点的值放入最终位置
void HeapSort (ElemType A,int len)
BuildMaxHeap(A,len) ;
//初始建堆
for(i = len; i > 1 ;i--)[
//n-1趟的交换和建堆过程
Swap(A[i], A[1]);
//输出堆顶元素(和堆底元素交换)
HeadAdjust(A, 1, i-1);//调整,把剩余的i-1个元素整理成堆
归并排序
ElemType *B= (ElemType *)malloc((n+1)*sizeof (ElemType)); //辅助数组B
void Merge (ElemType A[],int low,int mid,int high)
//表A的两段A[low..mid]和A[mid+1..high]各自有序,将它们合并成一个有序表
for(int k = low; k <= high; k++)
B[k] = A[k]; //将A中所有元素复制到B中
for(i = low, j = mid+1, k=i; i <= mid && j <= high; k++)
if(B[i] <= B[j]) //比较B的左右两段中的元素
A[k] = B[i++]; //将较小值复制到A中
else
A[k]=B[j++];
//for
while(i <= mid) A[k++]=B[i++]; //若第一个表未检测完,复制
while(j <= high) A[k++]=B[j++]; //若第二个表未检测完,复制
void MergeSort (ElemType A[],int low,int high)
if(low<high)
int mid = (low+high) / 2; //从中间划分两个子序列
MergeSort(A, low, mid); //对左侧子序列进行递归排序
MergeSort (A, mid+1, high); //对右侧子序列进行递归排序
Merge(A, low, mid, high);//归并
//if
综合应用题
双向冒泡排序算法
编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
这种排序方法又称双向起泡。奇数趟时,从前向后比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最大的元素移动到序列尾部。偶数趟时,从后往前比较相邻元素的关键字,遇到逆序即交换,直到把序列中关键字最小的元素移动到序列前端。程序代码如下:
void BubbleSort (int a[], int n)
int low = 0, high = n-1;
bool falg = true;
while (low < high && flag)
flag = false;
for (i = low; i < high; i++)
if (a[i] > a[i+1])
swap(a[i], a[i+1]);
flag = true;
high--;
for (i = high; i > low; i--)
if (a[i] < a[i-1])
swap(a[i], a[i-1]);
flag = true;
low++;
奇数移动到偶数前面
已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前边的算法(要求时间最少,辅助空间最少).
本题可采用基于快速排序的划分思想来设计算法,只需遍历一次即可,其时间复杂度为O(n),空间复杂度为O(1)。假设表为L [1…n],基本思想是:先从前向后找到一个偶数元素L(i),再从后向前找到一个奇数元素L(j),将二者交换;重复上述过程直到i大于j。
算法的实现如下:
void movie (int a[], int len)
int i = 0, j = len - 1;
while (i < j)
while (i < j && a[i] % 2 != 0) i++;
while (i < j && a[j] % 2 != 1) j--;
if (i < j)
Swap(a[i], a[j]);
i++;
j--;
快排枢纽值随机
试重新编写考点精析中的快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的。
int Partition(int[] a, int low, int high)
int rand_index = low + rand() % (high - low + 1);
Swap (a[rand_index], a[low]); //将枢轴值交换到第一个元素
int pivot = a[low]; //置当前表中的第一个元素为枢轴值
int i = low;
for (int j = low + 1; j <= high; j++)
if (a[j] < pivot) //找到后,交换到前面
swap(a[++i], a[j]);
swap(a[i], a[low]); //将基准元素插入最终位置
return i; //返回基准元素的位置
快排找第k小元素
试编写一个算法,使之能够在数组L[1…n]中找出第k小的元素(即从小到大排序后处于第k个位置的元素)。
在这里插入代码片
```![在这里插入图片描述](https://img-blog.csdnimg.cn/52c1812e20c3485c8866655c1de411e4.png)
```cpp
int kth_elem(int a[], int low, int high, int k)
int pivot = a[low];
int low_temp = low;
int high_temp = high;
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;
if (low == k)
return a[low];
else if (low > k)
return kth_elem(a, low_temp, low-1, k);
else
return kth_elem(a, low+1, high_temp, k);
荷兰国旗图案
荷兰国旗问题:设有一个仅由红、白、蓝三种颜色的条块组成的条块序列,请编写一个时间复杂度为O(n)的算法,使得这些条块按红、白、蓝的顺序排好,即排成荷兰国旗图案。
算法思想:顺序扫描线性表,将红色条块交换到线性表的最前面,蓝色条块交换到线性表的最后面。为此,设立三个指针,其中,j为工作指针,表示当前扫描的元素,i以前的元素全部为红色,k以后的元素全部为蓝色。根据j所指示元素的颜色,决定将其交换到序列的前部或尾部。初始时i=0,k=n-1,算法的实现如下:
void Flag_arrange(color a[], int n)
int i = 0, j = 0, k = n-1;
while (j <= k)
switch (a[j])
case RED: Swap(a[i], a[j]); i++; j++; break;
case White: i++; j++; break;
case RED: Swap(a[k], a[j]); k--; break;
// 没有j++防止交换后a[j]仍为蓝色
以上是关于2023数据结构考研复习-排序的主要内容,如果未能解决你的问题,请参考以下文章