排序:插入,希尔,堆,快速,归并排序

这几天把学到的几种排序整理了一下。除了之前发过的冒泡和选择,别的我都发出来了。

首先是插入排序

/*
2017年8月3日19:12:27
目的 : 插入排序  (升序)
*/

#include<stdio.h>


void insertsort(int *a, int len)
{
	int i,j;    //i表示第几个元素插入到前已经排序好的数组中
				//j表示从i前面一个开始找i应该被插入的位置
	
	int tmp ;
	for(i=1;i<len;i++)   //下标从一开始,第一个默认排序
	{
		j = i-1;
		tmp = a[i];
		while(j>=0 && a[j]>tmp)
		{
			a[j+1] = a[j]; 		//把比tmp大的都往后面移一个
			j--;
		}
		a[j+1] = tmp;     //当循环结束,j是指向第一个比他小的元素,若没有,则就是这个数组的一个的前面一个。
	}
}

void printA(int *a,int len)
{
	int i;
	for(i=0;i<len;i++)
		printf("%4d",a[i]);
	printf("\n");
}


int main()
{
	int a[10] = {9,8,7,6,5,4,3,2,1,0};
	int len = sizeof(a)/sizeof(a[0]);
	
	insertsort(a,len);
	printA(a,len);
	
	return 0;
}


然后是希尔排序

/*
2017年8月3日19:12:27
目的 : 希尔排序(升序) 
思路 : 插入排序是每一个一个找,插入,希尔是每d个,把一个数组竟可能排序号,最后调用一次插入排序
*/

#include<stdio.h>

void printA(int *a,int len)
{
	int i;
	for(i=0;i<len;i++)
		printf("%4d",a[i]);
	printf("\n");
}

void shellsort(int *a ,int len )
{
	int i,j;
	int d = 0;
	while(d<len)
	{
		d = d*3 +1;   //保存初始间隔    0 1 4 13 ..
	}
	while(d>0)
	{
		//内部就是插入排序,间隔为d
		for(i=1;i<len;i++)   
		{
			int tmp = a[i];
			j = i-d;
			while(j>=0 && a[j]>tmp)   //大于就往前走
			{
				a[j+d] = a[j];
				j = j-d;
			}
			a[j+d] = tmp;
		}
		d = (d-1)/3;
	}
	
}

int main()
{
	int a[10] = {9,8,7,6,5,4,3,2,1,0};
	int len = sizeof(a)/sizeof(a[0]);
	
	shellsort(a,len);
	printA(a,len);
	
	return 0;
}


堆排序
/*
2017年8月3日20:13:47
目的 : 堆排序  (升序)
思路 : 要实现一个二叉树堆,最关键是利用二叉树的一些性质, 
		这里的推排序,并不是真正去创建一个二叉树堆,而是通关二叉树堆的性质去模拟堆。
		数组,内存,都是线性的,我们要做的,就是通过代码把一个非线性的东西通过线性的东西表示
*/

#include<stdio.h>

//输出
void printA(int *a,int len)
{
	int i;
	for(i=0;i<len;i++)
		printf("%4d",a[i]);
	printf("\n");
}

//交换
void swap (int a[], int i, int j)
{
	int tmp = a[i];
	a[i] = a[j];
	a[j] = tmp;
}

//模拟一个二叉树堆排序的递归    先检查自己的结点,然后再去检查改变了结点的结点
//注意,这个函数只能检查当前结点以及改变了以后的子节点的二叉堆排序,并不是检查整个二叉树
void r_heap(int *a,int i,int len)     //这里需要三个变量,len是用来表示递归退出条件的
{
	int left = 2*i +1;
	int right = 2*i +2;
	int max = i;
	
	if (left < len && a[left] > a[max] )
		max = left;
	if(right < len && a[right] > a[max] )
		max = right;
	
	if (max != i)
	{
		swap(a,i,max);
		r_heap(a,max);  //递归调用,应为子结点该表,所以要检查改变的
	}
	
}

//堆排序
void heapsort(int *a,int len)
{
	int have_child = len/2 -1;      //满二叉树性质,非叶结点有(len/2 -1)个
	int i;
	for(i=have_child;i>;i++)      //实现创建堆
	{
		r_heap(a,i,len);
	}
	
	for(i=len-1;i>0;i--)     //不用i=0的的情况
	{
		swap(a,0,i);
		r_heap(a,0,--len);   //调整根节点
	}
}

int main()
{
	int a[10] = {9,8,7,6,5,4,3,2,1,0};
	int len = sizeof(a)/sizeof(a[0]);
	

	heapsort(a,len);
	
	printA(a,len);
	
	return 0;
}


归并排序

/*
2017年8月3日20:13:47
目的 : 归并排序
思路 :归并排序是吧一个数组,分成两部分,排好序在合并。
	   左边,右边的再分成两部分,实现递归。
	   需要注意的是,归并排序需要一个缓冲区,用来短暂保存合并后的数据。
*/

#include<stdio.h>

//输出
void printA(int *a,int len)
{
	int i;
	for(i=0;i<len;i++)
		printf("%4d",a[i]);
	printf("\n");
}

//交换
void swap (int a[], int i, int j)
{
	int tmp = a[i];
	a[i] = a[j];
	a[j] = tmp;
}

void merge(int *a,int left,int right,int mid,int *tmp)
{
	int i = left;
	int j = mid+1;
	int k = 0 ;
	while(i<=mid && j<=right)
	{
		if(a[i] <= a[j])
			tmp[k++] = a[i++];
		else 
			tmp[k++] = a[j++];
	}
	while(i<=mid)
		tmp[k++] = a[i++];
	while(j<=right)
		tmp[k++] = a[j++];
	
	k = 0;
	for(i=left;i<=right;i++)
	{
		a[i] = tmp[k++];
	}
	
} 

void mergesort(int *a,int left,int right,int *tmp)
{
	int mid = (left+right)/2;
	if(left<right)
	{
		mergesort(a,left,mid,tmp);
		mergesort(a,mid+1,right,tmp);
		merge(a,left,right,mid,tmp);
	}
}

int main()
{
	int a[10] = {9,6,8,0,3,5,2,4,7,1};
	int len = sizeof(a) / sizeof(a[0]);
	int tmp[10];
	
	mergesort(a,0,9,tmp);
	
	printA(a,len);
	return 0;
}

最后是快速排序,我写了两个,一个是以前写的,整体思路都是一样的,实现方法有一点不同。

/*
2017年8月2日17:29:42
目的 :快速排序
快速排序最重要的是实现找到排序数在当前排序的位置,然后递归排序前面的,在递归排序后面的
*/

#include<stdio.h>

void quikcsort(int *a,int low,int high);   //快速排序
int find(int *a,int low,int high) ;        

int main()
{
	int a[10] = {34,3,46,21,24,46,83462,6,12385,23553};
	
	quikcsort(a,0,10);
	
	int i;
	for(i=0;i<10;i++)
	{
		printf("%8d",a[i]);
	}
	printf("\n");
	
	return 0;
}

void quikcsort(int *a,int low,int high)
{
	int pos;
	if(low<high)
	{
		pos = find(a,low,high);
		quikcsort(a,low,pos-1);
		quikcsort(a,pos+1,high);
	}
	return ;
}

int find(int *a,int low,int high)      //找第一个元素所在数组的位置
{
	int val = a[low];
	while(low<high)
	{
		while(low<high && a[high]>=val)  //大于等于最好,保证稳定性
			high--;
		a[low] = a[high];
		while(low<high && val>=a[low])
			low++;
		a[high] = a[low];
	}
	a[low] = val;
	
	return low;
}

//45 和 48 不能同时出现两个等于  不然就是死循环。  一个就可以



/*
2017年8月4日11:46:36
目的 :快速排序
思路 :快速排序的思路都是找到一个标志,然后找到标志所在数组中的位置,然后左边和右边的进行递归
*/

#include<stdio.h>

//输出
void printA(int *a,int len)
{
	int i;
	for(i=0;i<len;i++)
		printf("%4d",a[i]);
	printf("\n");
}

//交换
void swap (int a[], int i, int j)
{
	int tmp = a[i];
	a[i] = a[j];
	a[j] = tmp;
}

//找最后一个数在整个数组的位置
int find(int *a,int left,int right)  
{
	int tmp = a[right];
	int index = left;
	int i;
	for(i=left;i<right;i++)
	{
		if( a[i] < tmp )
		{
			swap (a,i,index);
			index++;
		}
	}
	swap(a,index,right);
	
	return index;
}

void quicksort(int *a,int left,int right)
{
	if(left < right)
	{
		int pos = find(a,left,right);
		quicksort(a,left,pos-1);
		quicksort(a,pos+1,right);
	}
}

int main()
{
	int a[10] = {9,8,7,6,5,4,3,2,1,0};
	int len = sizeof(a)/sizeof(a[0]);
	

	quicksort(a,0,9);
	
	printA(a,len);
	
	return 0;
}




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值