浙大2020年Mooc数据结构笔记–第九讲 排序(上)
〇、前言
- 这几天开始跟着学数据结构,鉴于当初数据结构实在学的太弱,加之这项工作算是为大家之后复习、机试铺路。确实是一个迫切需要做的大规模工作。行胜于言,虽然从第二篇开始,坚持下去。
- 此文部分为自己写,部分参考网上内容。提前说一下哈。期待批评指正
一、简单排序
void Insertion_Sort(ElementType A[],int N){
for(P = 1;P<N;P++){
Tmp = A[P];
for(int i = P;i>0&&A[i - 1]>Tmp;i++){
A[i] = A[i-1];
}
A[i] = Tmp;
}
}
void Bubble_Sort(ElementType A[],int N){
for(P = N -1;P>=0;P--){
flag = 0;
for(int i = 0;i<P;i++){ //一趟冒泡
if(A[i] > A[i+1]){
Swap(A[i],A[i+1]);
flag = 1;//标识发生交换
}
}
if(flag == 0) break;//全程无交换
}
}
二、希尔排序
三、堆排序
四、归并算法
五、课后题
1、7-12 排序 (25分)
比较各个排序算法的时间复杂度,此处使用的是二路归并排序
#include<iostream>
#include<malloc.h>
using namespace std;
#define MAXN 100010
int num[MAXN];
//将arr[low...mid]和arr[mid+1...high]两个相邻的有序子序列归并为一个有序子序列arr[low...high]
void Merge(int arr[],int low,int high,int mid)
{
int *tmp;
int i = low,j = mid+1;
int k = 0;
tmp = (int *)malloc((high-low+1)*sizeof(int));
while(i<=mid&&j<=high)
{
if(arr[i]<arr[j])
{
tmp[k] = arr[i];
i++,k++;
}
else
{
tmp[k] = arr[j];
k++,j++;
}
}
while(i<=mid)
{
tmp[k] = arr[i];
i++,k++;
}
while(j<=high)
{
tmp[k] = arr[j];
j++,k++;
}
for(k = 0,i = low;i<=high;i++,k++)
{
arr[i] = tmp[k];
}
free(tmp);
}
void MergeSort(int arr[],int low,int high)
{
int mid;
if(low<high)
{
mid = (low+high)/2;
MergeSort(arr,low,mid);
MergeSort(arr,mid+1,high);
Merge(arr,low,high,mid);
}
}
int main()
{
int n;
cin>>n;
for(int i = 0;i<n;i++)
{
cin>>num[i];
}
MergeSort(num,0,n-1);
for(int i = 0;i<n;i++)
cout<<num[i]<<((i==n-1)?(""):" ");
return 0;
}
2、Insert or Merge 2014
判断是插入排序还是归并排序
Sample Input 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
Sample Output 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
Sample Input 2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
Sample Output 2:
Merge Sort
1 2 3 8 4 5 7 9 0 6
#include <iostream>
#include <cstdio>
#include <cstdlib>
#define N 1000
bool cmp(int arr1[], int arr2[], int n);
void merge(int arr1[], int num, int cnt, int start);
bool mergesort(int arr1[], int arr2[], int num);
bool insertsort(int arr1[], int arr2[], int num);
int main(int argc, char** argv) {
int arr1[N], arr2[N], arr3[N], num, i;
scanf("%d", &num);
for(i = 0; i < num; i++){
scanf("%d", &arr1[i]);
arr2[i] = arr1[i];
}
for(i = 0; i < num; i++){
scanf("%d", &arr3[i]);
}
if(insertsort(arr1, arr3, num)){
puts("Insertion Sort");
printf("%d", arr1[0]);
for(i = 1; i < num; i++){
printf(" %d", arr1[i]);
}
putchar('\n');
}
else{
mergesort(arr2, arr3, num);
puts("Merge Sort");
printf("%d", arr2[0]);
for(i = 1; i < num; i++){
printf(" %d", arr2[i]);
}
putchar('\n');
}
return 0;
}
bool cmp(int arr1[], int arr2[], int n){
int i;
for(i = 0; i < n; i++){
if(arr1[i] != arr2[i]){
return false;
}
}
return true;
}
void merge(int arr1[], int num, int cnt, int start){
int i, j, k, arr2[N];
i = start;
j = i + cnt;
k = 0;
while(i < start + cnt && j < start + 2 * cnt && j < num){
if(arr1[i] > arr1[j]){
arr2[k++] = arr1[j++];
}
else{
arr2[k++] = arr1[i++];
}
}
while(i < start + cnt && i < num){
arr2[k++] = arr1[i++];
}
while(j < start + 2 * cnt && j < num){
arr2[k++] = arr1[j++];
}
for(i = 0; i < k; i++){
arr1[start + i] = arr2[i];
}
return;
}
bool mergesort(int arr1[], int arr2[], int num){
int cnt = 1, i;
bool flag = false;
while(cnt < num && !flag){
for(i = 0; i < num; i += 2 * cnt){
merge(arr1, num, cnt, i);
}
cnt *= 2;
flag = cmp(arr1, arr2, num);
}
for(i = 0; i < num && flag; i += 2 * cnt){
merge(arr1, num, cnt, i);
}
return flag;
}
bool insertsort(int arr1[], int arr2[], int num){
int i, j, tmp;
bool flag = false;
for(i = 1; i < num && !flag; i++){
tmp = arr1[i];
for(j = i - 1; j >= 0; j--){
if(arr1[j] < tmp){
break;
}
else{
arr1[j + 1] = arr1[j];
}
}
arr1[j + 1] = tmp;
flag = cmp(arr1, arr2, num);
}
tmp = arr1[i];
for(j = i - 1; j >= 0 && flag; j--){
if(arr1[j] < tmp){
break;
}
else{
arr1[j + 1] = arr1[j];
}
}
arr1[j + 1] = tmp;
return flag;
}
3、Insertion or Heap Sort
与上一题类似,只需要排序一次比较一次即可
Sample Input 1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
Sample Output 1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
Sample Input 2:
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9
Sample Output 2:
Heap Sort
5 4 3 1 0 2 6 7 8 9
/***************2019.5.15-09:38-11:03**************/
//09-排序3 Insertion or Heap Sort
#include<stdio.h>
#include<algorithm>
using namespace std;
//*************
//InsertSort
//*************
void InsertSort(int Insert[],int step,int N){
int i;
int tmp=Insert[step];
for(i=step;i>0&&tmp<Insert[i-1];i--) Insert[i]=Insert[i-1];
Insert[i]=tmp;
}
//*************
//HeapSort
//*************
void Swap(int A[],int p,int q){
int tmp=A[p];
A[p]=A[q];
A[q]=tmp;
}
void AdjustHeap(int Heap[],int p,int Last){
int Parent,Child;
int tmp=Heap[p];
for(Parent=p;Parent*2+1<Last;Parent=Child){
Child=Parent*2+1;
if(Child+1<Last&&Heap[Child+1]>Heap[Child]) Child++;
if(Heap[Child]>tmp) Heap[Parent]=Heap[Child];
else break;
}
Heap[Parent]=tmp;
}
void BuildMaxHeap(int Heap[],int N){
int i;
for(i=(N-1)/2;i>=0;i--){ //从下到上调整每一课子树
AdjustHeap(Heap,i,N);
}
// for(i=0;i<N;i++) printf("%d ",Heap[i]);
}
void HeapSort(int Heap[],int step,int N){
int Last=N-step;
if(Last<=0) return;
Swap(Heap,0,Last);
AdjustHeap(Heap,0,Last);
}
//*************
//Match
//*************
int Match(int A[],int Sorted[],int N){
int i;
for(i=0;i<N;i++){
if(A[i]!=Sorted[i]) return 0;
}
return 1;
}
//*************
//main
//*************
int main(){
int i;
int N;
scanf("%d",&N);
int Sorted[N],Insert[N],Heap[N];
for(i=0;i<N;i++){
scanf("%d",&Insert[i]);
Heap[i]=Insert[i];
}
for(i=0;i<N;i++) scanf("%d",&Sorted[i]);
BuildMaxHeap(Heap,N); //需要先在比较前建起最大堆才能同步step
int step=1;
int flag=0;//1:Insert,2:Heap
while(step<N){
InsertSort(Insert,step,N);
if(Match(Insert,Sorted,N)){
flag=1;
break;
}
else HeapSort(Heap,step,N);
if(Match(Heap,Sorted,N)){
flag=2;
break;
}
step++;
}
if(flag==1){
printf("Insertion Sort\n");
InsertSort(Sorted,step+1,N);
}
else if(flag==2){
printf("Heap Sort\n");
HeapSort(Sorted,step+1,N);
}
for(i=0;i<N;i++){
printf("%d",Sorted[i]);
if(i<N-1) printf(" ");
else printf("\n");
}
return 0;
}