各类排序算法及思想

这篇博文就是自己的一些学习记录,部分数据fromhttp://data.biancheng.net/view/65.html
第一部分 插入排序
1.直接排序
基本思想:把数组分为两个部分,前一部分是有序序列;后一部分是无序序列;依次将无序序列中的第一个元素插入到有序序列当中去(从1到n-1),完成排序。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

void directsort(list &L){
	int i,j,min; 
	for(i=1;i<L.length;i++){
		if(L.data[i]<L.data[i-1]){
			min=L.data[i];
			for(j=i-1;min<L.data[j]&&j>0;--j){
			//注意这里一定要加上判断j>0,因为L.data[-1]也可能>min
			  L.data[j+1]=L.data[j];
		    }
			L.data[j+1]=min;  
		}
	} 
}

2.折半插入排序
算法思想:把数组分为两个部分,前一部分是有序序列;后一部分是无序序列;依次将无序序列中的第一个元素插入到有序序列当中去(从1到n-1),完成排序。这里与直接插入有区别的地方是,这里查找插入位置的时候不是逐个去比较元素大小,而是采用二分查找的方式去找到合适位置,提高了查找效率,一定程度上缩小了时间复杂度。

void insertsort(list &N){
	int i,j;
	int min,mid,low,high;
	for(i=1;i<N.length;i++){
		min=N.data[i];
		low=0;high=i-1;
		while(low<=high){
			mid=(low+high)/2;
			if(N.data[mid]>min)
			 high=mid-1;
			else
			 low=mid+1;	
		}
		for(j=i-1;j>=high+1;j--){//这里high+1也可以用low表示
			N.data[j+1]=N.data[j];
		}
		N.data[high+1]=min;
	}
}

3.希尔排序
算法思想:把表中的记录分为d组这样每次对d组的内容进行排序(每个组内采用直接插入排序)。
按照希尔的分法,n=8;A[]={3,2,5,4,1,6,7,8}
第一次d1=n/2组,这样每组2个元素进行排序。
如下:初始{3,1},{2,6},{5,7},{4,8}
排序结束{1,3},{2,6},{5,7},{4,8}
{1,2,5,4,3,6,7,8,}
第二次d2=d1/2,这样每组4个元素进行排序。
初始:{1,5,3,7},{2,4,6,8}
排序结束{1,3,5,7,},{2,4,6,8}
{1,2,3,4,5,6,7,8}
第三次d3=d2/2,这样每组8个元素进行排序。由于有序所不用进行换位置了。

void shellsort(list &N){
   	int i,j,min,dk;
	for(dk=N.length/2;dk>=1;dk=dk/2)
   	 for(i=dk+1;i<=N.length;++i)
   	  if(N.data[i]<N.data[i-dk])
		{
   	 	  min=N.data[i];
   	 	  for(j=i-dk;j>0&&min<N.data[j];j-=dk){
   	 	  //注意这里一定要加上判断j>0,因为N.data[-dk]也可能>min
   	 	  	N.data[j+dk]=N.data[j];
			}
			N.data[j+dk]=min;
		}
}

第二部分 交换排序
1.冒泡排序
基本思想:每一次把最小的元素放到最前面,循环n-1次,为什么循环n-1次,因为最后一个元素不用比较,肯定是最大的。

void swap(int &a,int &b){
	int c;
	c=a;
	a=b;
	b=c;
}
void bubblesort(int a[],int n){
	int i,j;
	bool flag;
	int i;
	for(i=0;i<n-1;i++){
		flag=false;
		for(j=n-1;j>i;j--) //最小的放在前面
			if(a[j]<a[j-1]){
				swap(a[j],a[j-1]);
				 flag=true;
				  }  		
	if(flag==false)
		return;
	}
} 

2.快速排序
基本思想:采用分治法,在待排序表中任意取一个元素为基准,比如A[0];通过一趟排序把排序表划分为两个独立的部分L[1…K-1]和L[K+1…n],使得左边部分小于L[k],右边的部分大于L[k];这样基准元素就放到合适位置上。然后,再分为左边和右边一起开始排序。

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 QuickSort(int a[],int low,int high){
	if(low<high){
		int pos=partition(a,low,high);
		QuickSort(a,low,pos-1);
		QuickSort(a,pos+1,high);
	}
}

第三部分选择排序
1.简单选择排序
基本思想:在L[i+1]到L[n]中选择关键字最小的元素与L[i]进行交换。

void swap(int &a,int &b){
	int c;
	c=a;
	a=b;
	b=c;
}
void SelectSort(int a[],int n){
	int min;
	for(int i=0;i<n-1;i++){
		for(int j=i+1;j<n;j++)
		  if(a[j]<a[i]){
		  	swap(a[i],a[j]);
		  }
	}
} 

2.堆排序
基本思想:1.构建大根堆(小根堆);2.输出大根堆的根节点,交换堆顶和堆底元素;3.把剩余的i-1个元素整理成堆。
构建大根堆的基本思想:1.n表示元素的个数,从n/2位置开始遍历,直到遍历完所有根节点;
1)若孩子节点都小于双亲节点,则调整结束。
2)若存在孩子节点大于双亲节点,则将最大的孩子节点与双亲节点进行交换,并对孩子节点进行1),2)直到出现1)或者叶节点为止。

void AdjustDown(int a[],int k,int len){
	a[0]=a[k];
	for(int i=2*k;i<=len;i*=2){
		if(a[i]<a[i+1]&&i<len) i++;
		if(a[0]>=a[i]) break;
		else{
			a[k]=a[i];
			k=i;
		}
	}
	a[k]=a[0];
}

void BuildMaxHeap(int a[],int len){
  for(int i=len/2;i>0;i--) 
    AdjustDown(a,i,len);	
}

void heapsort(int a[],int len){
	BuildMaxHeap(a,len);
	for(int i=len;i>=1;i--){
		printf("%d \t",a[1]);
		swap(a[i],a[1]);
		AdjustDown(a,1,i-1);
	}
}
//这里如果要插入一个新节点在底部,则可以向上调整 
void AdjustUp(int a[],int k){
	a[0]=a[k];
    int i=k/2;
    while(i>0&&a[i]<a[0]){  //父节点小于子节点 
    	a[k]=a[i];//父节点赋值给子节点 
		k=i;//子节点变成了i 
		i=k/2; 
	}
	a[k]=a[0];
}

第四部分归并排序
基本思想:将一个有序表从n/2处分开,分为前后相邻的两个有序表,然后将这两个有序表合并成一个新表,前面小,后面大。

//二路归并排序
//第一步合并两个有序线性表 
int *b=(int *)malloc((10)*sizeof(int));//有一个空间b[0]是不做操作的。 
void merge(int a[],int low,int mid,int high){
  	//将表A两端各自有序空间合成一个有序表
	for(int k=low;k<=high;k++)
		b[k]=a[k];//将A中所有元素复制到b中
	int i,j,k;	 
	for(i=low,j=mid+1,k=i;i<=mid&&j<=high; k++){
		if(b[i]<=b[j])
		  a[k]=b[i++];
		else
		  a[k]=b[j++];
	}
	while(i<=mid)
	  a[k++]=b[i++];
	while(j<=high)
	  a[k++]=b[j++];
}
//归并排序
void MergeSort(int 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);
	}
} 

如有疏漏,请多指教,未完待续!

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值