标签:
1、冒泡(Bubble)
7 5 2 1 5 9
5 7 2 1 5 9
5 2 7 1 5 9
5 2 1 7 5 9
5 2 1 5 7 9
2 5 1 5 7 9
2 1 5 5 7 9
2 1 5 5 7 9
1 2 5 5 7 9
public static void BubbleSort(int[] a)
{
int n = a.Length - 1;//个数
int i, j;//用于控制循环
int tmp;//中间变量
bool isChange;//记录冒泡一轮下来是否发生交换(如果没有发生交换证明已排好序)
for (i = 0; i < n; i++)
{
isChange = false;
for (j = 0; j < n - i; j++)//每轮冒泡过后要对比的数就少一个
{
if (a[j] > a[j + 1])//大的数向上冒
{
tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
isChange = true;
}
}
if (!isChange)
{
return;
}
}
return;
}
2、直接插入(Insert)
7 5 2 1 5 9
5 7 2 1 5 9
2 5 7 1 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void InsertSort(int[] a)
{
int n = a.Length;
for (int i = 1; i < n; i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
{
int temp = a[i];//temp标记为未排序第一个元素
int j = i - 1;
while (j >= 0 && a[j] > temp)//将temp与已排序元素从小到大比较,寻找temp应插入的位置
{
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
}
3、直接选择(Select)
7 5 2 1 5 9
1 5 2 7 5 9
1 2 5 7 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void SelectSort(int[] a)
{
int n = a.Length;//个数
int i, j;
int tmp;
int b;
for (i = 0; i < n - 1; i++)
{
tmp = i;
for (j = i + 1; j < n; j++)
{
if (a[tmp] > a[j])//每轮找到最小的元素
tmp = j;
}
if (i != tmp)
{
b = a[tmp];
a[tmp] = a[i];
a[i] = b;
}
}
}
4、快速(Quick)
7 5 2 1 5 9
5 2 1 5 7 9
2 1 5 5 7 9
1 2 5 5 7 9
public static void QuickSort(int[] a, int low, int high)
{
if (low < high)
{ // ↓ ↓
int point = MovePart(a, low, high);// 5 6 2 1 4 9 4 1 2 5 6 9
QuickSort(a, low, point);
QuickSort(a, point + 1, high);
}
}
public static int MovePart(int[] a, int partLow, int partHigh)
{
int pivotP = partLow;//记住枢纽位置
while (partLow < partHigh)
{
while (partLow < partHigh && a[partHigh] >= a[pivotP])//右往左找第一个小于pivot的数
{
partHigh--;
}
Swap(a, pivotP, partHigh);
pivotP = partHigh;
while (partLow < partHigh && a[partLow] <= a[pivotP])//左往右找第一个大于prvot的数
{
partLow++;
}
Swap(a, partLow, pivotP);
pivotP = partLow;
}
return pivotP;//返回分割点
}
public static void Swap(int[] a, int pivotP, int swapP)
{
int t;
t = a[pivotP];
a[pivotP] = a[swapP];
a[swapP] = t;
}
5、希尔(Shell)
7 5 2 1 5 9
7 5 2 1 5 9
7 5 2 1 5 9
5 7 2 1 5 9
2 5 7 1 5 9
2 5 7 1 5 9
1 2 5 7 5 9
1 2 5 5 7 9
public static void ShellSort(int[] a)
{
int n = a.Length;
for (int incr = 3; incr > 0; incr--)//增量递减,增量据说以9 5 3 1最优(各种大牛到现在都没有定论),此处为3 2 1
{
for (int L = 0; L < (n - 1) / incr; L++)//重复分成的每个子列表
{
for (int i = L + incr; i < n; i += incr)//对每个子列表应用插入排序
{
int temp = a[i];
int j = i - incr;
while (j >= 0 && a[j] > temp)
{
a[j + incr] = a[j];
j -= incr;
}
a[j + incr] = temp;
}
}
}
}
6、归并(Merge)
7 5 2 1 5 9
7 5 2 1 5 9
7 5 2 1 5 9
7 2 5 1 5 9
2 5 7 1 5 9
1 2 5 5 7 9
public static void Merge(int[] a, int low, int center, int high)
{
if (low >= high) return;
int m = center - low + 1;
int n = high - center;
int[] L = new int[m];
int[] R = new int[n];
int i, j, k;
for (i = 0; i < m; ++i) L[i] = a[low + i];//取得左边数
for (i = 0; i < n; ++i) R[i] = a[low + i + m];//取得右边数
for (i = 0, j = 0, k = low; i < m && j < n; ++k)
{
if (L[i] > R[j])//从L、R两边选比较小的数放进a,直到一边放完
{
a[k] = R[j];
j++;
}
else
{
a[k] = L[i];
i++;
}
}
while (i < m)//如果是L没放完,把L剩余的数放进a
{
a[k] = L[i];
k++;
i++;
}
while (j < n)//如果是R没放完,把R剩余的数放进a
{
a[k] = R[j];
k++;
j++;
}
}
public static void MergeSort(int[] a, int low, int high)
{
int center;
if (low < high)
{
center = (low + high) / 2;
MergeSort(a, low, center);
MergeSort(a, center + 1, high);
Merge(a, low, center, high);
}
}
7、堆(Heap)
7 5 2 1 5 9
7
/ \
5 2
/ \ / \
1 5 9
9
/ \
5 7
/ \ / \
1 5 2
/// <summary>
/// 堆排序,此处为倒序,要升序,请使用大二叉堆,或对数组进行首尾交换
/// </summary>
/// <param name="a"></param>
/// <param name="n"></param>
public static void HeapSort(int[] a, int n)
{
MakeMinHeap(a, n);//将数组建立成最小堆
for (int i = n - 1; i >= 1; i--)
{
Swap(a, i, 0);//把该论得到的最小数排到末尾已拍好序的的数前
MinHeapFixDown(a, 0, i);//排除末尾拍好序的的数得出子二叉堆,在作调整得出新的二叉堆,root又为最小的数
}
}
/// <summary>
/// 新加入叶子结点
/// </summary>
/// <param name="a"></param>
/// <param name="leafPoint">叶子结点所在位置</param>
public static void MinHeapAddPoint(int[] a, int leafPoint)//以叶子结点,叶子结点的父结点,叶子结点的爷结点...为一组进行直接插入
{
int fartherPoint, temp,currentPornt;
temp = a[leafPoint];
currentPornt = leafPoint;//记录当前节点位置
fartherPoint = (leafPoint - 1) / 2; //父结点
while (a[fartherPoint] > a[currentPornt]&& currentPornt!=0)
{
a[currentPornt] = a[fartherPoint];
currentPornt = fartherPoint;
fartherPoint = (currentPornt - 1) / 2;//父结点为的位置为 (currentPoint - 1) / 2
}
a[currentPornt] = temp;
}
/// <summary>
/// 在最小堆中加入新的数据num (从叶子结点(数组尾)插入)
/// </summary>
/// <param name="a"></param>
/// <param name="n">新增结点位置(数组结尾位置+1 即 数组长度)</param>
/// <param name="num">新增结点值</param>
public static void MinHeapAddNumber(int[] a, int n, int num)
{
a[n] = num;
MinHeapAddPoint(a, n);
}
/// <summary>
/// 删除跟结点(将最后的结点a[n]放到根节点a[0]的位置)后的堆调整
/// 从i整节点向下开始调整,n为节点总数, 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
/// </summary>
/// <param name="a">数组</param>
/// <param name="fatherPoint">要调整的位置</param>
/// <param name="n">二叉堆的长度(要调整到数组的那个位置)</param>
public static void MinHeapFixDown(int[] a, int fatherPoint, int n)
{
int sonPoint, temp;
temp = a[fatherPoint];
sonPoint = 2 * fatherPoint + 1;//左子结点,右子节点为sonPoint+1 子节点为 2*i+1, 2*i+2
while (sonPoint <n)
{
if (sonPoint + 1 < n && a[sonPoint + 1] < a[sonPoint]) //存在右子结点的话,在左右孩子中找较小数
sonPoint++;
if (a[sonPoint] >= temp)//再和父结点对比,如果父结点比较大不用做交换
break;
else
{//否则把较小的子结点往上移动,替换它的父结点
a[fatherPoint] = a[sonPoint];
fatherPoint = sonPoint;
sonPoint = 2 * fatherPoint + 1;
}
}
a[fatherPoint] = temp;
}
/// <summary>
/// 在最小堆中删除数(删除根节点)
/// </summary>
/// <param name="a"></param>
/// <param name="n">结点个数</param>
public static void MinHeapDeleteNumber(int[] a, int n)
{
Swap(a, 0, n - 1); //互换根节点和叶子结点后
MinHeapFixDown(a, 0, n - 1);//向下调整
}
/// <summary>
/// 建立最小堆 n为结点总数
/// </summary>
/// <param name="a">数组</param>
/// <param name="n">结点总数</param>
public static void MakeMinHeap(int[] a, int n)
{
for (int i = (n-1-1)/ 2 ; i >= 0; i--)//由最后一个结点的父结点开始向下调整
MinHeapFixDown(a, i, n);
}标签:
原文地址:http://my.oschina.net/moks/blog/361815