插入排序,希尔排序,堆排序,选择排序,快排,归并,实现和优化

1.插入排序:从头开始遍历,当前的和前面的数去比较,如果小的话,插到前面,时间复杂度o(n^2);

#include<stdio.h>
void quik(int array[],int sz)
{
     int *arr = array;

       int start = 0;
	   int end = sz-1;
	   int i = 0;
	   for(start = 0; start<end; start++)
	   {
	        for(i=start; i>=0; i--)
			{
			int tmp = 0;
			    if(arr[i+1] < arr[i])
				 {
				    tmp = arr[i];
					arr[i] = arr[i+1];
					arr[i+1] = tmp;
					}
		   }
		}

}

2.希尔排序:它是对插入排序的优化,经测得他 的效率是插入排序的100倍左右。

思想:主要是把它分为几组grep,先对它几组几组的来个伪排序,grep越小越接近排好的序列,最后用插入排序

 只需要把i++ 变为 i += grep,start +=grep,每次grep= grep/3即可

3.选择排序

思想:每次选一个最小的放在最前面,下面是优化的版本,在选最小的时候,选出一个最大的放在最后面

void sort(int *arr,int sz)
{
      int i =0;
	  int j = 0;
	  for(i=0; i<sz; i++,sz--)
	  {
	  int min = i;
	  int max = sz-1;
	  int tmp = 0;
	  int ret = 0;
	      for(j=i; j<sz; j++)
		  {
		     if(arr[j] < arr[min])
			  {
                 min = j;
			  }
			  if(arr[j] > arr[max])
			  max = j;
		 }
		      tmp = arr[i];
		      ret = arr[sz-1];
             arr[i] = arr[min];
             
              if(max == i)
              max = min;
			 arr[min] = tmp;
			 arr[sz-1] = arr[max];
			 arr[max] = ret;

	}
		     
 }

快速排序:每次随机产生一个值,把小的放在它左边,大的放在它右边

int oncesort(int *arr,int n,int start,int end)
{ 
     int i = 0;
     int index = 0;
	 int small = start-1;
	 int tmp = 0;
      idnex = rand()%n;
     while(index <start || index>end)
   index =	rand()%n;
	 tmp = arr[index];
	 arr[index] = arr[end];
	 arr[end] = tmp;
	 for(i=start; i<end; i++)
	 {
	      if(arr[i] < arr[end])
		  {
		     ++small;
			 if(small != i)
			  {
			 int  temp = arr[small];
			   arr[small] = arr[i];
			   arr[i] = temp;
			   }
			   }
		}
		++small;
		tmp = arr[small];
		arr[small] =arr[end];
		arr[end] = tmp;

		return small;


  }  
void sort(int *arr,int sz,int start,int end)
{
int index = 0;
   if(start == end)
   return;
   index = oncesort(arr,sz,start,end);
    if(index>start)
	 sort(arr,sz,0,index-1);
	 if(index < end)
	 	   sort(arr,sz,index+1,end);
     
	}

堆排序:先以完全二叉树创建一个大堆,然后每次把第一个最大值放到最后,在重新向上调整堆,

void ADjustDown(int *arr,int n ,int root)
{
   int parent = root;
   int child = root*2+1;
    
     while(child<=n)
	 {
	    if(arr[child]<arr[child+1] && child+1<=n)
		{
		    child++;
		}
		if(arr[child] >arr[parent])
		{
		   int tmp = arr[child];
		   arr[child] = arr[parent];
		   arr[parent] = tmp;
		   parent = child;
		   child = parent*2+1;
		}
		else
		  break;
		}
}
void sort(int *arr,int sz)
{
      int i =sz;
	  int end =sz-1;
	  for(i=(sz-1)/2; i>=0; i--)
	  {
	     ADjustDown(arr,sz-1,i);
		}
		while(end>0)
		{
		    int tmp = arr[0];
			arr[0] = arr[end];
			arr[end] = tmp;
			end--;
			ADjustDown(arr,end,0);
		}
	  

}

归并:归并的思想和二分查找类似,先把它分成一半然后在各自再分成一半,一直到它们只剩一个值得时候,合并两个数组。

优点:归并是稳定的算法,时间复杂度为O(log2n)

缺点:浪费了O(n)的空间、

void merge(int*arr,int start1,int end1,int start2,int end2,int *tmp)
{
  int ret = start1;

    int index = start1;
   while(start1 <= end1 && start2 <= end2)
   {
       if(arr[start1] < arr[start2])
        {
		  tmp[index++] = arr[start1++];
		  }
		  else
		  tmp[index++] = arr[start2++];
	}

	 while(start1 <= end1)
	 {
	     tmp[index++] = arr[start1++];
     }
	  while(start2 <= end2)
	  {
	     tmp[index++] = arr[start2++];
	  }
   memcpy(arr+ret,tmp+ret,sizeof(int)*((end2-ret)+1));
}
void mergesort(int *arr,int start,int end,int *tmp)
{
  int mid = start+((end-start)>>1);
  
   if(start == end)   // 当只剩一个数的时候开始合并
   return;
   mergesort(arr,start,mid,tmp);
   mergesort(arr,mid+1,end,tmp);
   merge(arr,start,mid,mid+1,end,tmp);
}

猜你喜欢

转载自blog.csdn.net/congjichukaishi/article/details/82706844