C语言排序算法
C语言基础排序算法
(用 a[0] 存储a数组中元素的个数)
1. 插入排序
(1). 直插排序
void InsertSort( int a[] , int len )
{
int i,j;
for(i = 2 ; i <= len ; ++i)
{
if(a[i] < a[i-1])
{
a[0] = a[i]; //用 a[0] 存储最后一个元素
a[i] = a[i-1];
for(j = i-1; a[j] > a[0] ; --j)
{
a[j] = a[j-1];
}
a[j+1] = a[0];
}
}
}
(2). 希尔排序
- 直接插入排序在记录个数较少且基本有序时,效率较 高。
- 希尔排序(Shell Sort) 将记录序列分成若干子序列, 分别对每个子序列进行插入排序。例如:将n 个记录 分成d 个子序列:
R[1],R[1+d],R[1+2d],… R[2],R[2+d],R[2+2d],… … R[d],R[2d],R[3d],… 其中,d
称为增量,它的值在排序过程中从大到小逐 渐缩小,直至最后一趟排序减为1。 -
希尔排序示例
void ShellInsert(int r[],int dk)
{
int i,j;
for(i = dk+1; i <= sizeof(r); ++i)
{
if(r[i] < r[i-dk])
{
r[0] = r[i];
for(j = i - dk; j > 0 && r[0] < r[j]; j -= dk)
r[j+dk] = r[j];
r[j+dk] = r[0];
}
}
}
void ShellSort(int r[],int dt[],int t)
{
for(int i = 0; i < t; ++i)
ShellInsert(r,dt[i]);
}
2. 交换排序
(1). 冒泡排序
void BubbleSort(int a[] ,int len)
{
int i,j;
for( i = 1; i < len; ++i )
{
for( j = len ; j > i ; --j)
{
if( a[j] < a[j-1] )
swap( a[j], a[j-1] ) ;
}
}
}
(3). 快速排序
- 任取一个记录(如第一个) 为枢轴
- 划分(Partitioning):所有比枢轴小的记录一律前
放,比枢轴大的记录一律后放,形成左右两个子
表 - 对子表重新前两步,直到每个子表的元素只一个。
- 初始化:low 指向第一条记录,high 指向最后一条记录。
- 交替执行下面两步,直至low 等于high,即为枢轴位
置。
(1)从右边扫找到第一个小于枢轴的记录,将其移到左边
(2)从左边扫找到第一个大于枢轴的记录,将其移到右边
//方法一:
#include <stdio.h>
#include <stdlib.h>
int q[101];
int tmp[100];
void swap(int *a,int *b){
int c = *a;
*a = *b;
*b = c;
}
int Partition(int a[],int low,int high)
{
int key = high-1;
for(int i = low;i < high;++i){
if(a[i] < a[key]){
swap(&a[i],&a[low]);
++low;
}
}
swap(&a[key],&a[low]);
return low;
}
void QuickSort(int a[],int low,int high)
{
if(low >= high) return;
int pivotkey = Partition( a, low, high );
QuickSort( a, low, pivotkey );
QuickSort( a, pivotkey + 1, high );
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i < n;i++)
scanf("%d",&q[i]);
QuickSort(q,0,n);
printf("===============\n");
for(int i=0;i < n;i++)
printf("%d\n",q[i]);
return 0;
}
//方法二:
#include<iostream>
using namespace std;
const int N = 1e6+10;
int n;
int q[N];
//快速排序---分治
//找出一个分界点,然后将分界点左侧的和右侧的分别进行排序
void quick_sort(int q[] ,int l,int r)
{
if( l >= r ) return;
int x = q[(l+r)/2]; //确定分界点
int i = l-1;
int j = r+1;
while(i < j)
{
do i++; while( q[i] < x);
do j--; while(q[j] > x);
if(i < j) swap(q[i],q[j]);
}
quick_sort(q , l ,j);
quick_sort(q, j+1,r);
}
int main()
{
cin>>n;
for(int i = 0;i < n; i++) cin>>q[i];
quick_sort(q, 0 ,n-1);
cout<<"================"<<endl;
for(int i = 0; i < n-1 ;i++ ) cout<<q[i]<<endl;
cout<<q[n-1]<<endl;
return 0;
}
3. 选择排序(Selection Sort)
(1).简单选择排序
n 条记录,循环n-1 次,每次选出从剩下记录中选出最小的与位置i的记录交换。
void SelectSort( int a[] , int n )
{
int i,j,minIndex;
for( i = 0 ;i < n-1 ; ++i )
{
minIndex = i ;
for( j = i+1 ; j < n ;j++ )
{
if( a[j] < a[minIndex] )
minIndex = j;
}
swap( a[i] , a[minIndex] ) ;
}
}
(2)堆排序
- 堆(Heap) 是满足下列性质的数列fk1; k2; …; kng
大根(顶) 堆: ki >= k2i 且ki >= k2i+1 ( 1 <= i <= ⌊n/2⌋ )
小根(顶) 堆: ki <= k2i且ki <= k2i+1 ( 1 <= i <= ⌊n/2⌋ ) - 堆是一个完全二叉树,并且每个结点的值都不小于(不大于) 其左右孩子结点的值
系列{96; 83; 27; 38; 11; 09} 为大根堆
-
堆排序代码
void HeapAdjust(int a[], int s, int m)
{//假设a[s+1 .. m] 已经是堆,将a[s .. m]调整为以a[s]为根的大顶堆
a[0] = a[s]; //用a[0]临时存储
int j ;
for( j = s*2 ; j <= m ; j *= 2 )
{
if( j < m && a[j] < a[j+1] ) //选择大
j++;
if(a[j] <= a[0])
break; //应插在s位置上
a[s] = a[j] ;
s = j ;
}
a[s] = a[0];
}
//创建一个堆
void Create_Heap(int a[],int len)
{
for(int i = len/2 ; i >= 1 ; i--) //从第一个非叶子结点的位置开始调整
HeapAdjust( a, i, len ) ;
}
//
void Heap_Sort(int a[] , int len)
{
Create_Heap(a , len);
for(int i = len ; i > 1 ; i--)
{
swap( a[i] , a[1] ) ; //a[1]是堆顶,
HeapAdjust(a, 1, i-1) ; //每次把堆顶换为最大的数(调整为大顶堆)
}
}
5. 归并排序
//方法一
void Merge(int a[] , int b[] , int low , int mid , int high)
{
int i = low,j = mid+1,k = low;
while(i <= mid && j <= high)
{
if(a[i] >= a[j]) b[k++] = a[j++];
else b[k++] = a[i++];
}
while(i <= mid) b[k++] = a[i++];
while(j <= high) b[k++] = a[j++];
}
int S[1000];
void MSort(int R[],int T[],int low,int high)
{int mid;
if( low == high) T[low] = R[low];
else
{ mid = (low + high) / 2;
MSort( R , S , low , mid ) ;
MSort( R , S , mid+1 , high ) ;
Merge( S , T , low , mid , high ) ;
}
}
void MergeSort(int a[] , int n)
{
MSort( a , a , 1 , n ) ;
}
//方法二:
#include <iostream>
using namespace std;
const int N = 1e6+10;
int n;
int q[N];
int tmp[N];
//归并排序---分治nlogn
//先找中点,把左右两侧从小到大排序后得到两个有序数组,再将两个有序数组合并
void merge_sort(int q[] ,int l,int r)
{
if( l >= r ) return;
int mid = l+r >> 1;
int k=0, i = l, j = mid+1;
merge_sort(q,l,mid);merge_sort(q,mid+1,r);
while(i <= mid && j <= r)
{
if( q[i] >= q[j]) tmp[k++] = q[j++];
else tmp[k++] = q[i++];
}
while(i <= mid) tmp[k++] = q[i++];
while(j <= r ) tmp[k++] = q[j++];
for(i = l,j = 0; i <= r;i++,j++) q[i] = tmp[j];
}
int main()
{
cin>>n;
for(int i = 0;i < n; i++) cin>>q[i];
merge_sort(q, 0 ,n-1);
cout<<"================"<<endl;
for(int i = 0; i < n-1 ;i++ ) cout<<q[i]<<endl;
cout<<q[n-1]<<endl;
return 0;
}
5. stl 排序
vector<int>a;
sort( a.begin() , --a.end() );