【数据结构】排序

数据表(dataList):待排元素的集合。

排序码(key):排序的关键字。

排序的稳定性:若相等的两个元素经过排序后顺序仍不变则称排序算法是稳定的。

一个b站学习视频

一、快速排序

(一)原理
选择一个元素作为基准元素,将小于基准元素的都放在其左边,将大于基准元素的都放在其右边。这样序列就被划分为大于和小于基准元素的两部分。对这两部分分别递归处理。基准元素随意选。
(二)代码

//快速排序---我自己的板子
#include<iostream>
#include<cstdio>
#define N 100009
using namespace std;

int n;
int a[N];

void qsort(int l,int r)
{
	int mid=a[(l+r)>>1];
	int i=l,j=r;
	do{
		while(a[i]<mid) i++;
		while(a[j]>mid) j--;
		if(i<=j)
		{
			swap(a[i],a[j]);
			i++;
			j--;
		}
	}while(i<=j);
	if(l<j) qsort(l,j);
	if(i<r) qsort(i,r);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	qsort(1,n);
	for(int i=1;i<=n;i++) printf("%d ",a[i]); 
	return 0;
}     

//课本上的代码...考试用
#include"dataList.h"
template<class T>
void QuickSort(dataList<T>&L,const int left,const int right)
{
	if(left<right)
	{
		int pivotpos=L.Partition(left,right);
		QuickSort(L,left,pivotpos-1);
		QuickSort(L,pivotpos+1,right);
	}
} 

template<class T>
int dataList<T>::Partition(const int low,const int high)
{
	int pivotpos=low;Element<T>pivot=Vector[low];
	for(int i=low+1;i<=high;i++)
	{
		if(Vector[i]<pivot)
		{
			pivotpos++;
			if(pivotpos!=i) swap(Vector[pivotpos],Vector[i]);   //小于基准元素的交换到左侧 
		}
	}
	Vector[low]=Vector[pivotpos];	Vector[pivotpos]=pivot;
	return pivotpos;                                               //返回基准元素的位置 
};
 

(三)时间复杂度分析
O(nlogn)

二、堆排序

(一)原理:小根堆保证父亲小于两个儿子,大根堆保证父亲大于两个儿子。
(二)代码

//堆排 
#include<iostream>
#include<cstdio>
#define N 1000009
using namespace std;

int n,tot;
int d[N];

void up(int x)
{
	if(x==0) return;
	if(d[x]<d[x/2])
	{
		swap(d[x],d[x/2]);
		up(x/2);
	}
}

void down(int x)
{
	int nxt;
	if(x*2>tot) return;
	if(x*2+1>tot) nxt=x*2;
	else nxt=d[x*2]<d[x*2+1]?x*2:x*2+1;
	if(d[x]>d[nxt])
	{
		swap(d[x],d[nxt]);
		down(nxt);
	}
}
 
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		d[++tot]=x;
		up(tot);
	}
	for(int i=1;i<=n;i++)
	{
		cout<<d[1]<<" ";
		d[1]=d[tot--];
		down(1); 
	}	
}

#define DefaultSize 10;
template<class T>
struct Element
{
	T key;
	field otherdata;
	Element<T>& operator = (Element<T>&x)
	{
		key=x.key;
		otherdata=x.otherdata;
	}
	bool operator >= (Element<T>&x){return key>=x.key;}
	bool operator < (Element<T>&x){return key<x.key;}
};

template<class T>
class MaxHeap{
	public:
		MaxHeap(int sz=DefaultSize);//构造函数,建立空堆
		MaxHeap(Element<T>arr[],int n);//构造函数
		~Maxheap(delete []heap;)//析构函数
		bool Insert(Element<T>&x);//将x插入到最大堆中
		bool Remove(Element<T>&x);//删除堆顶上的最大元素
		bool IsEmpty() const{return currentSize==0;}
		bool IsFull() const{return currentSize==maxHeapSize;}
	private:
		Element<T>*heap;
		int currentSize;
		int maxHeapSize;
		void siftDown(int start,int m);//从start到m自顶向下调整
		void siftUp(int start);         //从start到0自底向上调整
		Swap(const int i,const int j)
		{
			Element<T>tmp=heap[i];
			heap[i]=heap[j];
			heap[j]=tmp;
	    }
};

template<class T>
void maxHeap<T>::siftDown(const int start,const int m)
{
	int i=start;int j=2*i+1;
	Element<T,E>temp=heap[i];//暂存子树根节点
	while(j<=m)                   //检查是否到最后 
	{
		if(j<m&&heap[j]<heap[j+1]) j++;//让child指向两子女的最大者
		if(temp>=heap[j]) break;
		else{
			heap[i]=heap[j];
			i=j;j=2*j+1;
		} 
	} 
	heap[i]=temp;
};
#include"maxheap.h"
template<class T>
void HeapSort(maxHeap<T>&H)
{
	for(int i=(currentSize-2)/2;i>=0;i--) siftDown(i,currentSize-1);
	//将表转换成堆
	for(int i=currentSize-1;i>=0;i--)
	{
		Swap(0,i);siftDown(0,i-1);
	} 
};

(三)时间复杂度
O(nlogn)

三、希尔排序

(一)原理:将数组下标相差gap的元素进行插入排序,然后不断缩小gap。
(二)代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100009
using namespace std;

int n;
int a[N]; 

void ShellSort()
{
	int j,temp,d;
	d=n/2;
	while(d>0)
	{
		for(int i=d+1;i<=n;i++)
		{
			temp=a[i];
			j=i-d;
			while(j>0&&a[j]>temp)
			{
				a[j+d]=a[j];
				j=j-d;
			}
			a[j+d]=temp;
		}
		d/=2;
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	ShellSort();
	for(int i=1;i<=n;i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
} 

#include"dataList.h"
template<class T>
void Shellsort(dataList<T>&L,const int left,const int right)
{
	int i,j,gap=right-left+1;
	Element<T>temp;
	do{
		gap=gap/3+1;
		for(i=left+gap;i<=right;i++)
		{
			if(L[i]<L[i-gap])
			{
				temp=L[i];j=i-gap;
				do{
					L[j+gap]=L[j];
					j=j-gap;
				}while(j>=left&&temp<L[j]);
				L[j+gap]=temp;
			}
		 } 
	}while(gap>1);
};

(三)时间复杂度
O(n^(1.3—2))

四、插入排序

(一)每一个元素与其前面已经有序的元素比较,插入到合适的位置。
(二)代码
(1)直接插入排序

#include"dataList.h"
template<class T>
void InsertSort(dataList<T>&L,const int left,const int right)
{
	Element<T>temp;int i,j;
	for(int i=left+1;i<=right;i++) //i是当前准备要插入的元素,1---i-1都是有序的 
	{                                         //一共需要插入n-1 
		if(L[i]<L[i-1])                      //需要插入 
		{
			temp=L[i];                       //保存当前插入元素,防止丢失 
			j=i-1;                           
			do{
				L[j+1]=L[j];j--;           //后移 
			}while(j>=left&&temp<L[j]);   //j必须是小于i的第一个元素 如果j大于i就需要一直跳 
			L[j+1]=temp;
		}
	}
} 

----------------------------------------
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000009
using namespace std;

int n;
int a[N];

void InsertSort(int a[],int left,int right)
{
	int temp,j; 
	for(int i=left+1;i<=right;i++)
	{
		if(a[i]<a[i-1])
		{
			temp=a[i];
			j=i-1;
			do{
				a[j+1]=a[j];j--;
			}while(j>=left&&a[j]>temp);
			a[j+1]=temp;
		}	  
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	InsertSort(a,1,n);
	for(int i=1;i<=n;i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
} 

 

(2)折半插入排序

#include"dataList.h"
template<class T>
void BinaryInsertSort(dataList<T>&L,const int left,const int right)
{
	Element<T>temp;int i,low,high,middle,k;
	for(int i=left+1;i<=right;i++)  //i为当前插入元素,一共插入n-1次,left---i-1都为有序的 
	{
		temp=L[i];low=left;high=i-1;          //在[left,high]区间内寻找大于a[i]的最小元素 
		while(low<=high)
		{
			middle=(low+high)/2;
			if(temp<L[middle])
			 high=middle-1;
			else low=middle+1;
		}
		for(k=i-1;k>=low;k--) L[k+1]=L[k];  //[low,i-1]后移 
		L[low]=temp;                    //low就是插入的位置 
	}
} 




#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100009
using namespace std;

int n;
int a[N];

void BinaryInsertSort(int a[],int left,int right)
{
	int i,low,high,middle,k,temp;
	for(int i=left+1;i<=right;i++)
	{
		temp=a[i];low=left;high=i-1;
		while(low<=high)
		{
			middle=(low+high)/2;
			if(a[middle]>temp)
			{
				high=middle-1;
			}else low=middle+1;
		}
		for(k=i-1;k>=low;k--) a[k+1]=a[k];
		a[low]=temp;
	}
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	BinaryInsertSort(a,1,n);
	for(int i=1;i<=n;i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
} 

(三)时间复杂度
(1)直接插入 O(n^2)
(2)折半插入 O(n^2)

五、归并排序

(一)原理:递归减少区间大小,然后再合并。
(二)代码

//归并排序 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,a[100009],tmp[100009];

void merge_sort(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int ii=l,jj=mid+1,k=l;
    while(ii<=mid&&jj<=r){
        if(a[ii]<a[jj])tmp[k++]=a[ii++];
        else tmp[k++]=a[jj++];
    }
    while(ii<=mid)tmp[k++]=a[ii++];
    while(jj<=r)tmp[k++]=a[jj++];
    for(int i=l;i<=r;i++)a[i]=tmp[i];
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    merge_sort(1,n);
    for(int i=1;i<=n;i++)cout<<a[i]<<" ";
    return 0;
}
//----------------------------------- 

#include"dataList.h"
template<class T>
void merge(dataList<T>&L1,dataList<T>&L2,const int left,const int mid,const int right)
{
	for(int k=left;k<=right;k++) L2[k]=L1[k];
 	int s1=left,s2=mid+1,t=left;
 	while(s1<=mid&&s2<=right)//s1和s2是检测指针,t是存放指针 
 	{
 		if(L2[s1]<=L2[s2]) L1[t++]=L2[s1++];
		 else L1[t++]=L2[s2++]; 
	}
	while(s1<=mid) L1[t++]=L2[s1++];
	while(s2<=right) L1[t++]=L2[s2++];
}

void mergeSort(dataList<T>&L,dataList<T>&L2,int left,int right)
{
	if(left>=right) return;
	int mid=(left+right)/2;
	mergeSort(L,L2,left,mid);
	mergeSort(L,L2,mid+1,right);
	merge(L,L2,left,mid,right); 
}

(三)时间复杂度
O(n log n)

六、选择排序

(一)原理: 每次选择没被选择元素中最小的放到已经排序的序列里。
(二)代码


//选择排序 
#include"dataList.h"
template<class T>
void SelectSort(dataList<T>&L,const int left,const int right)
{
	for(int i=left;i<right;i++)
	{
		int k=i;
		for(int j=i+1;j<=right;j++)
		{
			if(L[j]<L[k]) k=j;
		}
		if(k!=i) swap(L[i],L[k]);
	}
} 

============================================
#include<iostream>
#include<cstdio>
#define N 1000009
using namespace std;

int n,a[N];

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++)
	{
		int k=i;
		for(int j=i+1;j<=n;j++)
		{
			if(a[j]<a[k]) k=j;
		}
		swap(a[i],a[k]);
	}
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
} 

(三)时间复杂度
O(n^2)

七、冒泡排序

(一)原理:相邻元素不停交换,每次都会有一个最小的被挤到序列的一端。
(二)代码

//冒泡排序 
#include<iostream>
#include<cstdio>
#define N 100009
using namespace std;

int n;
int a[N];

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++)
	{
		for(int j=1;j<=n-i;j++)
		{
			if(a[j]>a[j+1]) swap(a[j],a[j+1]);
		}
	}
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
} 

(三)时间复杂度
O(n^2)

第一次用markdown....
整理太费时间了...不考的我下次不整了...

posted @ 2020-06-24 20:12  ANhour  阅读(293)  评论(0编辑  收藏  举报