数据结构排序
Posted zzyh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构排序相关的知识,希望对你有一定的参考价值。
数据表(dataList):待排元素的集合。排序码(key):排序的关键字。
排序的稳定性:若相等的两个元素经过排序后顺序仍不变则称排序算法是稳定的。
一、快速排序
(一)原理
选择一个元素作为基准元素,将小于基准元素的都放在其左边,将大于基准元素的都放在其右边。这样序列就被划分为大于和小于基准元素的两部分。对这两部分分别递归处理。基准元素随意选。
(二)代码
//快速排序---我自己的板子
#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....
整理太费时间了...不考的我下次不整了...
以上是关于数据结构排序的主要内容,如果未能解决你的问题,请参考以下文章
ElasticSearch学习问题记录——Invalid shift value in prefixCoded bytes (is encoded value really an INT?)(代码片段