基础排序算法

参考链接:http://blog.csdn.net/morewindows/article/category/859207

快排-冒泡-直接插入-直接选择-归并-堆排序

[swap]两数交换 不使用中间变量

inline void swap( int &a , int & b) 
{ 
         if (a != b) /需判断 可能会置0
        { 
                 // a^b = c  对c用a可以解出b 对c用b 可以解出a
                 a = a ^ b;
                 //对c 用旧b解锁得到 a;
                 b = b ^ a;
                 //对c 用b(旧 a)解锁得到b;
                 a = a ^ b;
        } 

         if(a != b)
        {
                 //总数
                 a = a + b;
                 //总数- 旧b = 旧 a
                 b = a - b;
                 //总数- 新b(旧 a) = 旧b
                 a = a - b;
        }
}  

【快速排序】【挖坑填坑】
算法思想:找到数组一个值(一般是第一个元素) 根据这个值把数组分成3堆,对这个堆进行递归
21  5  19  1
第一个数为准值
右边找小的
左边找大的
1 5 19 1
把准值扔到左右重叠的位置
1  5  19  21
准值 = 位置 = 3
判断(left<准值)     
递归(数组,0,准值-1);
判断(准值>right)
递归(数组,准值+1,right);

void q_sort (int numbers[], int left, int right )
{
         int pivot , l_hold, r_hold;

         l_hold = left ;
         r_hold = right ;

         //选取第一个元素作为阀值
         pivot = numbers [left];

         //以阀值为界限分组
         while (left < right)
        {
                 //右边找到一个比阀值小的循环结束
                 while ((numbers [right] >= pivot) && (left < right))
                         right--;
                 //假如找到把右边小的扔到左边去
                 if (left != right)
                {
                         numbers[left ] = numbers[ right];
                         left++;
                }
                 //左边找到一个比阀值大的循环结束
                 while ((numbers [left] <= pivot) && (left < right))
                         left++;
                 //假如找到把左边大的扔到右边去
                 if (left != right)
                {
                         numbers[right ] = numbers[ left];
                         right--;
                }
        }
        
         //把阀值放到left=right的地方
         numbers[left ] = pivot;
         //阀值记录为位置
         pivot = left ;

         //左右回到开始位置
         left = l_hold ;
         right = r_hold ;

         //左边到阀值前一个位置排序
         if (left < pivot)
                 q_sort(numbers , left, pivot-1);
         //阀值后一个位置到右边排序
         if (right > pivot)
                 q_sort(numbers , pivot+1, right);
}


【冒泡排序】

算法思想:
N个数字
1.比较前后2个数字,大的往后面走,最大就是最后一个
2.N=N-1,依此循环,N=0顺序就确定好了

void _bsort (int * arr,int size)
{
         //总共循环次数
         for(int i = 0; i < size ;i++)
                 //每次循环完确定一个最大然后缩小样本空间
                 for(int j = 1; j<size - i; j++)
                {
                         if (arr [j - 1] > arr[j ]) 
                                 swap(arr [j - 1], arr[j ]); 
                }
}

void _bsort_fast (int * arr,int size)
{
         int flag = size;
         int k = 0;
         while(flag > 0)
        {
                 //flag为某个位置后全部有序的标志位
                 k = flag ;
                 //假如有序了退出循环
                 flag = 0;
                 for(int i= 1; i<k ; i++)
                {
                         if(arr [i-1]> arr[i ])
                        {
                                 swap(arr [i-1], arr[i ]);
                                 flag = i ;
                        }
                }
        }
}

【插入排序】

算法思想:
1.数组a[0,n-1],令i=0;
2.a[0]有序,插入a[i],a[0..i]有序
3.i++,直到i=n-1排序完成

//小到大
void _insert_sort (int * arr,int size)
{
         int i ,j, k;
         for( i = 1;i < size;i ++)
        {
                 //为arr[i] 找位置
                 for( j = i-1; j >= 0; j --)
                {
                         if(arr [i] > arr[j ])
                                 break;
                }
                 //排除上面的循环没执行情况把下面语句加在 break上面也可以
                 //找到合适位置j插入 j后面的后移
                 if(j != i-1)
                {
                         //保存arr[i]
                         int temp = arr[ i]; 
                         //从a[i] 后面一位开始将比 a[i]大的数据向后移
                         for( k = i-1; k > j ;k--)
                                 arr[k +1] = arr[ k];
                
                         //将a[i] 放到正确位置上
                         arr[k + 1] = temp; 
                }
        }
}

void insertsort2 (int a[], int n) 
{ 
         int i , j; 
         for (i = 1; i < n; i ++) 
        {
                 //a[i]与前一位相比如果遇到比 a[i]小的有序
                 //假如前面的比a[i]大进行移位插入
                 if (a [i] < a[i - 1]) 
                { 
                         //记录a[i]
                         int temp = a[ i]; 
                         //条件语句是关键包括了搜索和移位
                         for (j = i - 1; j >= 0 && a [j] > temp; j --) 
                                 a[j + 1] = a[ j]; 
                         //a[i]插入
                         a[j + 1] = temp; 
                } 
        }
}  

//可以遍历第i个数前面的数
//可以比较第i个数和它前面的数
//eg:if(a[i]>a[j])
for(int i=1; i<n ; i++)
     for(int j= i-1; j >=0; j--)

void Insertsort3 (int a[], int n) 
{ 
         int i , j; 
         for (i = 1; i < n; i ++) 
                 for (j = i - 1; j >= 0; j --) 
                {       
                         //a[j]与前一位比较比它小就交换直到合适位置
                         if(a [j] > a[j +1])
                                 swap(a [j], a[j + 1]); 
                }
}  


【直接选择排序】

算法思想:与直接插入排序类似

1.数组a[0,n-1],令i=0;
2.a[0..i-1]有序,从无序区a[i,n-1]选择一个最小的,放到a[i]位置,使a[0,..i]有序
3.i++,直到i=n-1排序完成

void select_sort (int * arr, int size)
{
         int i , j , mid_pos;

         for(i =0; i< size; i ++)
        {
                 mid_pos = i ;
                 //搜索i 位置后面的元素
                 //得到比a[i] 小的数的位置
                 for(j =i+1; j<size ; j++)
                {
                         if(arr [mid_pos] > arr[j ])
                        {
                                 //记下最值得交换的位置
                                 mid_pos = j ;
                        }       
                }
                         //和arr[i] 交换位置a[0..i]有序
                 swap(arr[mid_pos], arr[i ]);
                
        }
}

【归并排序】

算法思想:

1.先递归分解数列,分到一个小组只有1个数据,有序
2.再合并对称的2个数组完成归并

void merge_array (int a[],int first, int mid , int last, int temp[])
{
         int first_a = first, end_a = mid ;
         int first_b = mid + 1, end_b = last ;
         int k = 0;

         //比较两个小数组小的到新数组
         while(first_a <= end_a && first_b <= end_b )
        {
                 if(a [first_a]> a[first_b ])
                         temp[k ++] = a[ first_b++];
                 else
                         temp[k ++] = a[ first_a++];
        }

         //可能有剩余的补上
         while(first_a <= end_a)
                 temp[k ++] = a[ first_a++];
         //可能有剩余的补上
         while(first_b <= end_b)
                 temp[k ++] = a[ first_b++];

         //拷贝到a
         for(int i=0; i<k ; i++)
                 a[first + i] = temp[i ];
}


void merge_sort (int a[], int first, int last , int temp[]) 
{ 
         if(first < last)
        {
                 int mid = (first + last) / 2;
                 //右边有序
                 merge_sort(a ,first, mid,temp );
                 //左边有序
                 merge_sort(a ,mid+1, last,temp );
                 //合并两边
                 merge_array(a ,first, mid,last ,temp);
        }
}  




【堆排序】

算法思想:
1.建立堆
2.排序


//增加操作是儿子节点找父亲节点调整父亲节点往上走
//删除操作时父亲节点(头节点 )找儿子节点调整儿子节点往下走

void heap_min_add_fix (int * arr,int pos)
{

         //i为新节点位置
         int i = pos;
         //j为父节点位置
         int j = (i-1)/2;
         int temp = arr[ i];

         while(j >=0)
        {
                 //假如父节点小不需要调整
                 if(arr [j] <= temp)
                         break;

                 //重新调整父节点、子节点位置
                 //父节点位置继续调整
                 arr[i ] = arr[ j];
                 i = j ;
                 j = (i -1)/2;
        }
         //新节点位置重新设置
         arr[i ] = temp;
}

void heap_min_add (int * arr,int pos, int data )
{
         arr[pos ] = data;
         heap_min_add_fix(arr ,pos);
}


//堆的删除每次只能删除头结点
void heap_min_delete_fix (int * arr,int pos , int nodesize )
{
         //father
         int i = pos;

         int temp = arr[ i];
         //son node
         int j = 2*i+1;

         while(nodesize >j)
        {
                 //左右孩子找到最小的
                 if(j +1<nodesize && arr[j +1]<arr[ j])
                         j++;

                 if(temp =< arr[ j])
                         break;

                 //小的节点往上走
                 arr[i ] = arr[ j];
                 i = j ; //新父亲节点
                 j = 2*i +1 //新儿子节点
        }
        
         //找到这个父亲节点赋值
         arr[i ] = temp;
}

void heap_min_delete (int * arr,int size)
{
         //最后一个节点与第一个节点交换
         //执行向下调整
         swap(arr [0],arr[ size-1]);
         heap_min_delete_fix(arr ,0,size-1);
}

void heap_create (int* arr, int size)
{
         //拿到最后一个父节点父节点往下修复
         for(int i=( size-1)/2;i >=0;i--)
                 heap_min_delete_fix(arr ,i, size-1);
}

void heap_sort_min (int * arr, int size)
{
         //每次拿a[n-1] 与a[0]交换
         //然后执行向下调整,调整 [0 -  n-2]
         //再执行a[n-2] 与a[0]交换
         //再往下执行调整,调整到 [0 - n-3]
         //每次将数据并入后面的有序区,完成后整个数组有序
         for(int i= size-1;i >=0; i++)
        {
                 swap(arr [0],arr[ i]);
                 heap_min_delete_fix(arr ,0,i);
        }
原文地址:https://www.cnblogs.com/guyan/p/2661666.html