排序算法 C#
1。选择排序
2。插入排序
插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子集中的适当位置,直到全部记录插入完成为止。
3。希尔排序
基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
4。快速排序
基本思想
设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解:
在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
注意:
划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
其中low≤pivotpos≤high。
②求解:
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
③组合:
因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。
5。冒泡排序
public class SelectionSorter
{
private int min;
public void Sort( int[] list )
{
// 从前到后遍历
for( int i = 0; i < list.Length-1; ++i )
{
min=i;
for( int j = i + 1; j < list.Length; ++j )
{
if( list[j] < list[min] )
min = j;// min就是剩下元素中最小的那个的索引值
}
// 交换最小值和当前值,达到从小到大的要求
int t = list[min];
list[min] = list[i];
list [i] = t;
}
}
}
{
private int min;
public void Sort( int[] list )
{
// 从前到后遍历
for( int i = 0; i < list.Length-1; ++i )
{
min=i;
for( int j = i + 1; j < list.Length; ++j )
{
if( list[j] < list[min] )
min = j;// min就是剩下元素中最小的那个的索引值
}
// 交换最小值和当前值,达到从小到大的要求
int t = list[min];
list[min] = list[i];
list [i] = t;
}
}
}
2。插入排序
插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子集中的适当位置,直到全部记录插入完成为止。
public class InsertionSorter
{
public void Sort( int [] list )
{
for( int i = 1; i < list.Length; ++i )
{
int t = list[i];
int j = i;
// 寻找插入点,从后往前把插入点后的元素后移
while( ( j>0 ) && ( list[j-1] > t ) )
{
list[j] =list[j-1];
--j;
}
list[j] = t;
}
}
}
{
public void Sort( int [] list )
{
for( int i = 1; i < list.Length; ++i )
{
int t = list[i];
int j = i;
// 寻找插入点,从后往前把插入点后的元素后移
while( ( j>0 ) && ( list[j-1] > t ) )
{
list[j] =list[j-1];
--j;
}
list[j] = t;
}
}
}
3。希尔排序
基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
public class ShellSorter
{
public void Sort(int[] list)
{
int inc;
// 确定合适的间隔
for(inc = 1; inc <= list.Length/9; inc = 3*inc+1);
for( ; inc > 0; inc /= 3) // 每次间隔缩短2/3
{
for( int i = inc + 1; i <= list.Length; i += inc )
{
int t = list[i-1];
int j = i;
// 插入排序
while( ( j > inc ) && ( list[j - inc - 1] > t ) )
{
list[j-1] = list[j - inc - 1];
j -= inc;
}
list[j-1] = t;
}
}
}
}
{
public void Sort(int[] list)
{
int inc;
// 确定合适的间隔
for(inc = 1; inc <= list.Length/9; inc = 3*inc+1);
for( ; inc > 0; inc /= 3) // 每次间隔缩短2/3
{
for( int i = inc + 1; i <= list.Length; i += inc )
{
int t = list[i-1];
int j = i;
// 插入排序
while( ( j > inc ) && ( list[j - inc - 1] > t ) )
{
list[j-1] = list[j - inc - 1];
j -= inc;
}
list[j-1] = t;
}
}
}
}
4。快速排序
基本思想
设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解:
在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
注意:
划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
其中low≤pivotpos≤high。
②求解:
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
③组合:
因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。
public class QuickSorter
{
private void Swap( ref int l, ref int r )
{
int s;
s = l;
l = r;
r = s;
}
public void Sort( int [] list, int low, int high )
{
int pivot;
int l,r;
int mid;
if( high <= low )
return;
else if( high == low+1 )
{
if( list[low] > list[high] )
Swap( ref list[low], ref list[high] );
return;
}
mid = (low+high) >> 1;
pivot = list[mid]; // 基准点
Swap( ref list[low], ref list[mid] );
l = low + 1;
r = high;
do
{
while( l <= r && list[l] < pivot ) // 在左边且比较小的,忽视
l++;
while( list[r] >= pivot ) // 在右边且比较大的,忽视
r--;
// 如果出现了左边一个元素大且右边一个元素小的话,就交换
if( l < r )
Swap( ref list[l], ref list[r] );
} while( l < r );
list[low] = list[r];
list[r] = pivot;
// 如果还需要递归左边或者右边的话
if( low+1 < r )
Sort( list, low, r-1 );
if( r+1 < high )
Sort( list, r+1, high );
}
}
{
private void Swap( ref int l, ref int r )
{
int s;
s = l;
l = r;
r = s;
}
public void Sort( int [] list, int low, int high )
{
int pivot;
int l,r;
int mid;
if( high <= low )
return;
else if( high == low+1 )
{
if( list[low] > list[high] )
Swap( ref list[low], ref list[high] );
return;
}
mid = (low+high) >> 1;
pivot = list[mid]; // 基准点
Swap( ref list[low], ref list[mid] );
l = low + 1;
r = high;
do
{
while( l <= r && list[l] < pivot ) // 在左边且比较小的,忽视
l++;
while( list[r] >= pivot ) // 在右边且比较大的,忽视
r--;
// 如果出现了左边一个元素大且右边一个元素小的话,就交换
if( l < r )
Swap( ref list[l], ref list[r] );
} while( l < r );
list[low] = list[r];
list[r] = pivot;
// 如果还需要递归左边或者右边的话
if( low+1 < r )
Sort( list, low, r-1 );
if( r+1 < high )
Sort( list, r+1, high );
}
}
5。冒泡排序
public class BubbleSorter
{
public void Sort(int[] R)
{
int i,j,temp;
bool isChanged;// 交换标志
//最多做R.Length-1趟排序
for( i = 0; i < R.Length; i++ )
{
//本趟排序开始前,交换标志应为假
isChanged = false;
for( j=R.Length - 2; j >= i; j-- )
{
// 出现左大于右的,则交换
if( R[j+1] < R[j] )
{
temp = R[j+1];
R[j+1] = R[j];
R[j] = temp;
//发生了交换,故将交换标志置为真
isChanged = true;
}
}
//本趟排序未发生交换,提前终止算法
if(!isChanged)
{
break;
}
}
}
}
{
public void Sort(int[] R)
{
int i,j,temp;
bool isChanged;// 交换标志
//最多做R.Length-1趟排序
for( i = 0; i < R.Length; i++ )
{
//本趟排序开始前,交换标志应为假
isChanged = false;
for( j=R.Length - 2; j >= i; j-- )
{
// 出现左大于右的,则交换
if( R[j+1] < R[j] )
{
temp = R[j+1];
R[j+1] = R[j];
R[j] = temp;
//发生了交换,故将交换标志置为真
isChanged = true;
}
}
//本趟排序未发生交换,提前终止算法
if(!isChanged)
{
break;
}
}
}
}