常用排序算法(快速排序,冒泡排序,最大公约数,Fibonacci )【原创】
(1)快速排序的算法是:
1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0];
3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值A[J],并与key交换;
4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于key的A[I],与key交换;
5)重复第3、4、5步,直到 I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i+或j-完成的最后另循环结束。)
例如:待排序的数组A的值分别是:(初始关键数据:X=49) 注意关键X永远不变,永远是和X进行比较,无论在什么位子,最后的目的就是把X放在中间,小的放前面大的放后面。
A[0] A[1] A[2] A[3] A[4] A[5] A[6]:
49 38 65 97 76 13 27
进行第一次交换后:27 38 65 97 76 13 49
( 按照算法的第三步从后面开始找)
进行第二次交换后:27 38 49 97 76 13 65
( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时:I=3 )
进行第三次交换后:27 38 13 97 76 49 65
( 按照算法的第五步将又一次执行算法的第三步从后开始找
进行第四次交换后:27 38 13 49 76 97 65
( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时:I=4,J=6 )
此时再执行第三步的时候就发现I=J,从而结束一趟快速排序,那么经过一趟快速排序之后的结果是:27 38 13 49 76 97 65,即所有大于49的数全部在49的后面,所有小于49的数全部在49的前面。
private void Q_Sort(int[] v_Arr, int v_low, int v_high)
{
int pv_pivottag = 0;
if (v_low < v_high)
{
pv_pivottag = Q_Move(v_Arr, v_low, v_high);
Q_Sort(v_Arr, v_low, pv_pivottag – 1);
Q_Sort(v_Arr, pv_pivottag + 1, v_high);
}
}
private int Q_Move(int[] v_Arr, int v_low, int v_High)
{
int lv_IntKey =v_Arr[v_low];
int lv_LeftIndex=v_low, lv_RightIndex=v_High;
int temp;
while (lv_LeftIndex < lv_RightIndex)
{
//从右边开始找到第一个比Key值小的
while (lv_LeftIndex < lv_RightIndex && v_Arr[lv_RightIndex] >lv_IntKey)
{
lv_RightIndex–;
}
//从左边开始找到第一个比Key值大的
while (lv_LeftIndex < lv_RightIndex && v_Arr[lv_LeftIndex] <=lv_IntKey)
{
lv_LeftIndex++;
}
//如果leftIndex < rightIndex,则交换左右动态下标所指定的值;
//在左边找到比Key值更大的,与右边第一个比Key值小的交换,然后继续while查找
//当leftIndex==rightIndex时,跳出整个循环
if (lv_LeftIndex < lv_RightIndex)
{
temp = v_Arr[lv_LeftIndex];
v_Arr[lv_LeftIndex] = v_Arr[lv_RightIndex];
v_Arr[lv_RightIndex] = temp;
}
}
//此时,两个动态指标是相同的
temp = lv_IntKey;
//当两个动态指标指向同一个时,便可以确定Key值
if (temp < v_Arr[lv_RightIndex])
{
//如果key小于两个指标同时指向的值,
//便将KeyValue 与RightIndex-1的值交换,并还回RightIndex-1
v_Arr[v_low] = v_Arr[lv_RightIndex – 1];
v_Arr[lv_RightIndex – 1] = temp;
return lv_RightIndex – 1;
}
else
{
v_Arr[v_low]=v_Arr[lv_RightIndex];
v_Arr[lv_RightIndex] = temp;
return lv_RightIndex;
}
}
(2)冒泡排序:
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],以此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,以此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。
for(i=0;i<N-1;i++)
{
for(j=0;j<N-i-1;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp}
}
}
(3)求最大公约数
给出两个正整数a和b,用b除a得商a0,余数r,写成式子 a=a0b+r,0≤r<b.
(1) 这是最基本的式子,辗转相除法的灵魂.如果r等于0,那么b可以除尽a,而a、b的最大公约数就是b. 如果r≠0,再用r除b,得商a1,余数r1,即 b=a1r+r1,0≤r1<r.
(2) 如果r1=0,那么r除尽b,由(1)也除尽a,所以r是a、b的公约数.反之,任何一除尽b的数,由(1),也除尽r,因此r是a、b的最大公约数. 如果r1≠0,则用r1除r得商a2,余数r2,即 r=a2r1+r2,0≤r2<r1.
(3) 如果r2=0,那么由(2)可知r1是b、r的公约数,由(1),r1也是a、b的公约数.反之,如果一数除得尽a、b,那末由(1),它一定也除得尽b、r,由(2),它一定除得尽r、r1,所以r1是a、b的最大公约数. 如果r2≠0,再用r2除r1,如法进行.由于b>r>r1>r2>…逐步小下来,而又都是正整数,因此经过有限步骤后一定可以找到a、b的最大公约数d(它可能是1).这就是有名的辗转相除法,在外国称为欧几里得算法.
这个方法不但给出了求最大公约数的方法,而且帮助我们找出x、y,使 ax+by=d.
(4)在说明一般道理之前,先看下面的例子. 从求42897与18644的最大公约数出发: 42897=2×18644+5609, (i) 18644=3×5609+1817, (ii) 5609=3×1817+158, (iii) 1817=11×158+79, (iv) 158=2×79. 这样求出最大公约数是79.
理解了上面的,就可以完成求三个以上的公约数了,算法如下:
刚开始,程序对输入的第一个和第二个数进行最大公约数运算,然后把所求得的最大公约数与输入的第三个数进行最大公约数运算,然后再把所求得的最大公约数与输入的第四个数进行最大公约数运算,以此类推,直到最后一个为止。
C#实现:
private void button1_Click(object sender, EventArgs e)
{
HGF lv_HGF = new HGF();
string lv_Str = string.Empty;
lv_HGF.HFG(textBox1.Text .Trim (),ref lv_Str);
textBox3.Text = lv_Str;
}
public class HGF
{
public void HFG(int v_Int1,int v_Int2,ref string v_Re)
{
int lv_Temp = 0;
if(v_Int1<v_Int2)
{
lv_Temp = v_Int1;
v_Int1 = v_Int2;
v_Int2 = lv_Temp;
}
while (v_Int2 != 0)
{
lv_Temp = v_Int1 % v_Int2;
v_Int1 = v_Int2;
v_Int2 = lv_Temp;
}
v_Re = v_Int1.ToString ();
}
public void HFG(string v_Str,ref string v_Re)
{
string[] lv_Arr = v_Str.Split(new string []{“,”}, StringSplitOptions .RemoveEmptyEntries);
HFG(Convert .ToInt32( lv_Arr[0].Trim ()),
Convert .ToInt32 ( lv_Arr[1].Trim ()),
ref v_Re);
if (lv_Arr.Length > 2)
{
for (int i = 2; i < lv_Arr.Length; i++)
{
HFG(Convert.ToInt32(lv_Arr[i].Trim()),
Convert.ToInt32(v_Re.Trim()),
ref v_Re);
}
}
}
}
(4)斐波那契数列:1、1、2、3、5、8、13、21、……
如果设F(n)为该数列的第n项(n∈N+)。那么这句话可以写成如下形式:
F(0) = 0,F(1)=1,F(n)=F(n-1)+F(n-2) (n≥2),
C#实现:
private void button_FiboNacci_Click(object sender, EventArgs e)
{
#region Method1
int x = 0, y = 1;
for (int i = 1; i < 12;i ++,y=x +y ,x =y-x )
{
textBox3.Text +=y .ToString ().PadRight (5) + ” “;
if (i % 4 == 0)
{
textBox3.Text += Environment.NewLine;
}
}
#endregion
#region Method2
textBox3.Text += Environment.NewLine;
for (int j = 0; j < 12; j++)
{
//使用递归
int temp = Fabonacci(j);
textBox3.Text += temp.ToString().PadRight(5) + ” “;
if (j % 4 == 0)
{
textBox3.Text += Environment.NewLine;
}
}
#endregion
}
private int Fabonacci(int num)
{
if (num < 3)
return 1;
else
return Fabonacci(num – 1) + Fabonacci(num – 2);
}