码迷,mamicode.com
首页 > 编程语言 > 详细

排序算法分析(二)

时间:2016-05-16 11:09:30      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:

直接选择排序:

原理:每次从未排序的序列中找到最小值,记录并最后存放到已排序序列的结尾

性能:时间复杂度为ON^2)空间复杂度为O1),排序是不稳定的(把最小值交换到已排序的结尾导致的),每次都能确定一个元素所在的最终位置,比较次数与初始序列无关。

 
void select_sort(int value[], int length)  
{  
      int i,j;
      for(i=0;i<length-1;i++)
      {
         int min=i;
         for(j=i+1;j<length;j++)
         {
            if(value[min]>value[j])
            {
                min=j;
             }
          }
          if(min!=i)
         {
             swap(value[i],value[min]);
         }
      }
  }

快速排序

    快速排序是对冒泡排序的一种改进。由C. A. R. Hoare1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

对于基准数的选择,本程序使用中间值作为基准数,下面是程序实现:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>

void swap(int *a ,int *b)
{
    int t = *a;
    *a = *b;
    *b = t;
}


int partition(int array[],int l,int r)
{
    int pivot = array[r];
    int curpos = l;
    int j ;

    for( j = l;j<r;j++)
    {
        if(array[j] < pivot)
        {
            swap(&array[j],&array[curpos]);
            curpos++;
        }
    }

    swap(&array[r],&array[curpos]);
    return curpos;
    
    
}

void quicksort(int array[],int l,int r)
{
    int interval;
    if(l < r)
    {
        interval = partition(array,l,r);
        quicksort(array,l,interval-1);
        quicksort(array,interval+1,r);
    }
        
}


int test_quicksort()
{	int i;
    int number = 12;
    int *array = malloc(number*sizeof(int));
    if(array == NULL)
    {
        printf("malloc failed\n");
        return -1;
    }
    
	

    printf("----------------------------------------before quick sort--------------\n");
    srand(time(NULL));
    for(i = 0;i<number;i++)
    {
        array[i] = rand()%1000;
        printf("\tarray[%d] = %d\n",i,array[i]);
    }

    printf("----------------------------------------after quick sort-----------------\n");
    
    quicksort(array,0,number-1);
    for(i = 0;i<number;i++)
    {
        printf("\tarray[%d] = %d\n",i,array[i]);
    }
    return 0;
}
int main()
{
    test_quicksort();
}


归并排序:

分而治之思想:

   1.Divide:  将n个元素平均划分为各含n/2个元素的子序列;

   2.Conquer:  递归的解决两个规模为n/2的子问题;

   3.Combine:  合并两个已排序的子序列。

性能:

   时间复杂度总是为O(NlogN),空间复杂度为O(N),算法与初始序列无关,排序也是稳定的

优化:

     1. 在规模较小时,合并排序可以采用直接插入

     2.在写法上,可以在生成辅助数组时,两头小,中间大,这是不需要在后边加两个while循环进行判断,只需一次比完。

  比较v[indexA]=7和v[indexB]=12,将较小的v[indexA]取出来放到临时向量tempArray中,然后indexA加1

  技术分享

代码:

   

#include<stdlib.h>   
typedef int RecType;//要排序元素类型  
void Merge(RecType *R,int low,int m,int high)  
{  
    //将两个有序的子文件R[low..m)和R[m+1..high]归并成一个有序的子文件R[low..high]  
    int i=low,j=m+1,p=0;                //置初始值  
    RecType *R1;                        //R1是局部向量  
    R1=(RecType *)malloc((high-low+1)*sizeof(RecType));  
    if(!R1)  
    {  
        return;                         //申请空间失败  
    }  
  
    while(i<=m&&j<=high)                //两子文件非空时取其小者输出到R1[p]上  
    {  
        R1[p++]=(R[i]<=R[j])?R[i++]:R[j++];  
    }  
  
    while(i<=m)                         //若第1个子文件非空,则复制剩余记录到R1中  
    {  
        R1[p++]=R[i++];  
    }  
    while(j<=high)                      //若第2个子文件非空,则复制剩余记录到R1中  
    {  
        R1[p++]=R[j++];  
    }  
  
    for(p=0,i=low;i<=high;p++,i++)  
    {  
        R[i]=R1[p];                     //归并完成后将结果复制回R[low..high]  
    }  
}  
  
void MergeSort(RecType R[],int low,int high)  
{     
    //用分治法对R[low..high]进行二路归并排序  
    int mid;  
    if(low<high)  
    {   //区间长度大于1   
        mid=(low+high)/2;               //分解  
        MergeSort(R,low,mid);           //递归地对R[low..mid]排序  
        MergeSort(R,mid+1,high);        //递归地对R[mid+1..high]排序  
        Merge(R,low,mid,high);          //组合,将两个有序区归并为一个有序区  
    }  
}  
void main()  
{  
    int a[7]={49,38,65,97,76,13,27}; //这里对8个元素进行排序  
    int low=0,high=6;                   //初始化low和high的值  
  
    printf("Before merge sort: ");  
    for(int i=low;i<=high;i++)  
    {  
        printf("%d ",a[i]);             //输出测试  
    }  
    printf("/n");  
  
    MergeSort(a,low,high);  
  
    printf("After merge sort:  ");  
    for( i=low;i<=high;i++)  
    {  
        printf("%d ",a[i]);             //输出测试  
    }  
    printf("/n");  
}   

 

优化代码:

void Merge(int arr[],int temp_arr[],int left,int mid,int right)  
{  
	//简单归并,先复制到temp_arr,再进行归并
    int i;
    for(i=left,i<=right;i++)
	{
		temp_arr[i]=arr[i];
	}
	int pa = left,
	int pb=mid+1;
	int index = left;
    while(pa<=mid && pb<=right) 
	{
		 //两子文件非空时取其小者输出到arr上  
		if(temp_arr[pa] <= temp_arr[pb])
		{
			arr[index++] = temp_arr[pa++];
		}
		else
		{
			arr[index++] = temp_arr[pb++];
		}
	}
    //复制没有比较完子表中的元素
    while(pa<=mid)                         //若第1个子文件非空,则复制剩余记录到R1中  
    {  
        arr[index++]=temp_arr[pa++];  
    }  
    while(pb<=right)                      //若第2个子文件非空,则复制剩余记录到R1中  
    {  
        arr[index++]=temp_arr[pb++];  
    }  
}  

void Merge_improve(int arr[],int temp_arr[],int left,int mid,int right)
{
	//优化归并;复制时,两头小,中间大,一次比较完
	int i;
	for(i=left;i<=mid;i++)
	{
		temp_arr[i]=arr[i];
	}
	for(i=mid+1;i<=right;i++)
	{
		temp_arr[i]=arr[right+mid+1-i];
	}
	int pa = left;
	int pb = right;
	int p = left;
	while(p<=right)
	{
		if(temp_arr[pa]<=temp_arr[pb])
		{
			arr[p++]=temp_arr[pa++];
		}
		else
		{
			arr[p++]=temp_arr[pb--];
		}
	}
}
void MergeSort(int arr[],int temp_arr[],int left,int right)  
{     
    //用分治法对R[left..right]进行二路归并排序   
    if(left<right)  
    {   //区间长度大于1   
        int mid=(left+right)/2;               //分解  
        MergeSort(arr,temp_arr,0,mid);           //递归地对R[low..mid]排序  
        MergeSort(arr,temp_arr,mid+1,right);        //递归地对R[mid+1..high]排序  
        Merge(arr,temp_arr,left,mid,right);          //组合,将两个有序区归并为一个有序区  
    }  
}  

void MergeSort(int arr[],int len)
{
	int *temp_arr = (int *)malloc(sizeof(int)*len);
	Mergesort(arr,temp_arr,0,len-1);
}

 

堆排序

原理


堆的性质:

是一棵完全二叉树

每个节点的值都大于或等于其子节点的值,为最大堆;反之为最小堆。

堆排序思想:

将待排序的序列构造成一个最大堆,此时序列的最大值为根节点


依次将根节点与待排序序列的最后一个元素交换

再维护从根节点到该元素的前一个节点为最大堆,如此往复,最终得到一个递增序列

性能


时间复杂度为O(NlogN),空间复杂度为O(1),因为利用的排序空间仍然是初始的序列,并未开辟新空间。算法是不稳定的,与初始序列无关。

使用场景

想知道最大值或最小值时,比如优先级队列,作业调度等场景。

代码

void shiftDown(int arr[], int start, int end)
     //从start出发到end,调整为最大堆 
      int dad = start; 
      int son = dad * 2 + 1;
      while (son <= end){ 
      //先选取子节点中较大的 
      if (son + 1 <= end && arr[son] < arr[son + 1])
         son++;
     //若子节点比父节点大,则交换,继续往子节点寻找;否则退出
     if (arr[dad] < arr[son])
            swap(arr[dad], arr[son]);
            dad = son; 
            son = dad * 2 + 1; 
         else
         { break; }
       }
      void heap_sort(int arr[], int len)
      { //先调整为最大堆,再依次与第一个交换,进行调整,最后构成最小堆
         for (int i = (len - 2) / 2; i >= 0; i--)
             //len为总长度,最后一个为len-1,所以父节点为 (len-1-1)/2
             shiftDown(arr,i,len-1); 
          for (int i = len - 1; i >= 0; i--)
              swap(arr[i], arr[0]);
              shiftDown(arr, 0,i-1); 
          }
      }
 

#include <stdio.h>  
#define N 1000  
#define INF 999999999  
int h[N];  
  
//调整堆(迭代法)  
//n:规模 i:二叉子堆的堆顶  
void  
heapAdjust(int n, int par)  
{  
    int tmp, pos, lc, rc;  
  
    while (par <= n/2) {  
        tmp = h[par]; //记录父母结点键值  
        lc = par<<1;  
        rc = lc+1;  
        pos = par;  
        //父母结点至多更新2次  
        if (h[par] < h[lc]) {  
            h[par] = h[lc];  
            pos = lc;  
        }  
        if (rc <= n && h[par] < h[rc]) {  
            h[par] = h[rc];  
            pos = rc;  
        }  
        if (pos == par) //无更新即无需调整  
            break;  
        else  
            h[pos] = tmp;  
        par = pos; //假设这个位置的结点是“父母结点”  
    }  
}  
  
//创建堆  
//规模为n的堆,对其父母结点,自底向上自右向左地调整堆  
void  
createHeap(int n)  
{  
    int i;  
  
    for (i = n/2; i != 0; i--) {  
        heapAdjust(n, i);  
    }  
}  
  
void  
heapSort(int n)  
{  
    int ntimes = n;  
  
    while (ntimes--) {  
        printf("%d\n", h[1]);  
        h[1] = h[n];  
        h[n--] = 0; //堆清零  
        heapAdjust(n, 1);  
    }  
}  
  
int  
main(void)  
{     
    int n, i;  
      
    scanf("%d", &n);  
    h[0] = INF;  
    for (i = 1; i != n+1; i++) {  
        scanf("%d", &h[i]);  
    }  
    createHeap(n);  
    heapSort(n);  
    return 0;  
}  




排序算法分析(二)

标签:

原文地址:http://blog.csdn.net/qq_24338883/article/details/51422149

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!