# C#算法

C#算法

using System;
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)
{
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 class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
ShellSorter sh=new ShellSorter();
sh.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}

using System;
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 class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
InsertionSorter ii=new InsertionSorter();
ii.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}

using System;
public class SelectionSorter
{
// public enum comp {COMP_LESS,COMP_EQUAL,COMP_GRTR};
private int min;
// private int m=0;
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;
}
int t=list[min];
list[min]=list[i];
list[i]=t;
//   Console.WriteLine("{0}",list[i]);
}
}
}
public class MainClass
{
public static void Main()
{
int[] iArrary=new int[]{1,5,3,6,10,55,9,2,87,12,34,75,33,47};
SelectionSorter ss=new SelectionSorter();
ss.Sort(iArrary);
for(int m=0;m<=13;m++)
Console.WriteLine("{0}",iArrary[m]);
}
}
已经成功的编译。

□非哥 发表于 2005-10-14 23:00:00
1、稳定排序和非稳定排序

a2,a3,a5就不是稳定的了。2、内排序和外排序

3、算法的时间复杂度和空间复杂度

================================================================================
*/

/*
================================================

================================================
*/
/*
====================================================

=====================================================
*/
void select_sort(int *x, int n)
{
int i, j, min, t;
for (i=0; i<n-1; i++) /*要选择的次数：0~n-2共n-1次*/
{
min = i; /*假设当前下标为i的数最小，比较后再调整*/
for (j=i+1; j<n; j++)/*循环找出最小的数的下标是哪个*/
{
if (*(x+j) < *(x+min))
{
min = j; /*如果后面的数比前面的小，则记下它的下标*/
}
}

if (min != i) /*如果min在循环中改变了，就需要交换数据*/
{
t = *(x+i);
*(x+i) = *(x+min);
*(x+min) = t;
}
}
}

/*
================================================

================================================
*/
/*
====================================================

=====================================================
*/
void insert_sort(int *x, int n)
{
int i, j, t;
for (i=1; i<n; i++) /*要选择的次数：1~n-1共n-1次*/
{
/*
暂存下标为i的数。注意：下标从1开始，原因就是开始时
第一个数即下标为0的数，前面没有任何数，单单一个，认为
它是排好顺序的。
*/
t=*(x+i);
for (j=i-1; j>=0 && t<*(x+j); j--) /*注意：j=i-1，j--，这里就是下标为i的数，在它前面有序列中找插入位置。*/
{
*(x+j+1) = *(x+j); /*如果满足条件就往后挪。最坏的情况就是t比下标为0的数都小，它要放在最前面，j==-1，退出循环*/
}
*(x+j+1) = t; /*找到下标为i的数的放置位置*/
}
}

/*
================================================

================================================
*/
/*
====================================================

=====================================================
*/
void bubble_sort(int *x, int n)
{
int j, k, h, t;

for (h=n-1; h>0; h=k) /*循环到没有比较范围*/
{
for (j=0, k=0; j<h; j++) /*每次预置k=0，循环扫描后更新k*/
{
if (*(x+j) > *(x+j+1)) /*大的放在后面，小的放到前面*/
{
t = *(x+j);
*(x+j) = *(x+j+1);
*(x+j+1) = t; /*完成交换*/
k = j; /*保存最后下沉的位置。这样k后面的都是排序排好了的。*/
}
}
}
}

/*
================================================

================================================
*/
/*
====================================================

=====================================================
*/
void shell_sort(int *x, int n)
{
int h, j, k, t;
for (h=n/2; h>0; h=h/2) /*控制增量*/
{
for (j=h; j<n; j++) /*这个实际上就是上面的直接插入排序*/
{
t = *(x+j);
for (k=j-h; (k>=0 && t<*(x+k)); k-=h)
{
*(x+k+h) = *(x+k);
}
*(x+k+h) = t;
}
}
}

/*
================================================

================================================
*/
/*
====================================================

C.A.R.Hoare于1962年提出的。

=====================================================
*/
void quick_sort(int *x, int low, int high)
{
int i, j, t;
if (low < high) /*要排序的元素起止下标，保证小的放在左边，大的放在右边。这里以下标为low的元素为基准点*/
{
i = low;
j = high;
t = *(x+low); /*暂存基准点的数*/
while (i<j) /*循环扫描*/
{
while (i<j && *(x+j)>t) /*在右边的只要比基准点大仍放在右边*/
{
j--; /*前移一个位置*/
}
if (i<j)
{
*(x+i) = *(x+j); /*上面的循环退出：即出现比基准点小的数，替换基准点的数*/
i++; /*后移一个位置，并以此为基准点*/
}
while (i<j && *(x+i)<=t) /*在左边的只要小于等于基准点仍放在左边*/
{
i++; /*后移一个位置*/
}
if (i<j)
{
*(x+j) = *(x+i); /*上面的循环退出：即出现比基准点大的数，放到右边*/
j--; /*前移一个位置*/
}
}
*(x+i) = t; /*一遍扫描完后，放到适当位置*/
quick_sort(x,low,i-1);  /*对基准点左边的数再执行快速排序*/
quick_sort(x,i+1,high);  /*对基准点右边的数再执行快速排序*/
}
}

/*
================================================

================================================
*/
/*
====================================================

*/
/*

*/
void sift(int *x, int n, int s)
{
int t, k, j;
t = *(x+s); /*暂存开始元素*/
k = s;  /*开始元素下标*/
j = 2*k + 1; /*右子树元素下标*/
while (j<n)
{
if (j<n-1 && *(x+j) < *(x+j+1))/*判断是否满足堆的条件：满足就继续下一轮比较，否则调整。*/
{
j++;
}
if (t<*(x+j)) /*调整*/
{
*(x+k) = *(x+j);
k = j; /*调整后，开始元素也随之调整*/
j = 2*k + 1;
}
else /*没有需要调整了，已经是个堆了，退出循环。*/
{
break;
}
}
*(x+k) = t; /*开始元素放到它正确位置*/
}

/*

*/
void heap_sort(int *x, int n)
{
int i, k, t;
int *p;
for (i=n/2-1; i>=0; i--)
{
sift(x,n,i); /*初始建堆*/
}
for (k=n-1; k>=1; k--)
{
t = *(x+0); /*堆顶放到最后*/
*(x+0) = *(x+k);
*(x+k) = t;
sift(x,k,0); /*剩下的数再建堆*/
}
}

void main()
{
#define MAX 4
int *p, i, a[MAX];
/*录入测试数据*/
p = a;
printf("Input %d number for sorting :\n",MAX);
for (i=0; i<MAX; i++)
{
scanf("%d",p++);
}
printf("\n");
/*测试选择排序*/

p = a;
select_sort(p,MAX);
/**/

/*测试直接插入排序*/
/*
p = a;
insert_sort(p,MAX);
*/

/*测试冒泡排序*/
/*
p = a;
insert_sort(p,MAX);
*/
/*测试快速排序*/
/*
p = a;
quick_sort(p,0,MAX-1);
*/
/*测试堆排序*/
/*
p = a;
heap_sort(p,MAX);
*/
for (p=a, i=0; i<MAX; i++)
{
printf("%d ",*p++);
}
printf("\n");
system("pause");
}

//为了说明方便.定义如下数组:  a:array[1..10] of integer;temp: 中间变量  排序:  从大到小
l         选择排序
1.基本的 选择排序
<1>基本思想
首先从要排序的数中选择最大的数,将它放在第一个位置,然后从剩下的数中选择最大的数放在第二个位置,如此继续,直到最后从剩下的两个数中选择最大的数放在倒数第二个位置,剩下的一个数放在最后位置,完成排序.
下表是六个元素的排序的过程

4    5   7   1   2   3
┗━━┛
5    4   7   1   2   3
┗━━━━┛
7    4   5   1   2   3
┗━━━━━━┛
7    4   5   1   2   3
┗━━━━━━━━━━┛    第一趟结束
⑦   4   5   1   2   3
┗━┛
7    5   4   1   2   3
┗━━━┛
7    5   4   1   2   3
┗━━━━━┛
7    5   4   1   2   3
┗━━━━━━━┛     第二趟结束
7    ⑤  4   1   2   3
┗━┛
7    5   4   1   2   3
┗━━━┛
7    5   4   1   2   3
┗━━━━━┛    第三趟结束
7    5   ④  1   2   3
┗━┛
7    5   4   2   1   3     第四趟结束
┗━━━┛
7    5   4   ③  1   2
┗━┛     第五趟结束
7    5   4   3   ②  ①

<2>算法实现
for i:=1 to 9 do
for j:=i+1 to 10 do
if a[i]<a[j]
begin
temp:=a[i];
a[i]:=a[j];
a[j]:=temp;
end;
2.改进
以上排序方案每次交换两个元素需要执行三个语句,过多的交换必定要花费许多时间.改进方案是在内循环的比较中找出最大值元素的下标,在内循环结束时才考虑是否要调换.
代码如下
for i:=1 to 9 do
begin
k:=i;
for j:=i+1 to 20 do
if a[j]>a[k]
then k:=j;
if i<k {不可能大于}
then begin
temp:=a[i];
a[i]:=a[k];
a[k]:=temp;
end;
end;

l         冒泡排序
1.基本的冒泡排序
<1> 基本思想
依次比较相邻的两个数,把大的放前面,小的放后面.即首先比较第1个数和第2个数,大数放前,小数放后.然后比较第2个数和第3个数......直到比较最后两个数.第一趟结束,最小的一定沉到最后.重复上过程,仍从第1个数开始,到最后第2个数.然后......
由于在排序过程中总是大数往前,小数往后,相当气泡上升,所以叫冒泡排序.
下面是6个元素的排序的过程

4     5    7    1    2    3
┗━━┛
5     4    7    1    2    3
┗━━┛
5     7    4    1    2    3
┗━━┛
5     7    4    1    2    3
┗━━┛
5     7    4    2    1    3
┗━━┛  第一趟结束
5     7    4    2    3    ①
┗━━┛
7     5    4    2    3    1
┗━━┛
7     5    4    2    3    1
┗━━┛
7     5    4    2    3    1
┗━━┛       第二趟结束
7     5    4    3    ②   1
┗━━┛
7     5    4    3    2    1
┗━━┛
7     5    4    3    2    1
┗━━┛            第三趟结束
7     5    4    ③   2    1
┗━━┛
7     5    4    3    2    1
┗━━┛                 第四趟结束
7     5    ④    3   2    1
┗━━┛                       第五趟结束
⑦    ⑤   4    3    2    1

<2> 算法实现
for i:=1 to 9 do
for j:=1 to 10-i do
if a[j]<a[j+1]
then begin
temp:=a[j];
a[j]:=a[j+1];
a[j+1]:=temp;
end;

2 改进
上例中,可以发现,第二趟结束已经排好序.但是计算机此时并不知道已经排好序.所以,还需进行一次比较,如果没有发生任何数据交换,则知道已经排好序,可以不干了.因此第三趟比较还需进行,第四趟、第五趟比较则不必要.
我们设置一个布尔变量bo 来记录是否有进行交换.值为false 进行了比较　true 则没有
代码如下
i:=1;
repeat
bo:=true;
for j:=1 to 10-i
if a[j]<a[j+1] then
begin
temp:=a[j];
a[j]:=a[j+1];
a[j+1]:=temp;
bo:=false;
end;
inc(i);
until bo;

3.再次改进
如果说是有20个元素．数据序列是8,3,4,9,7再后跟着１５个大于９且已经排好序的数据．在第三趟后算法终止．总共做了19+18+17=54次比较使得绝大多数已排好序的数据在一遍扫描后足以发现他们是排好序的情况下仍然被检查３遍．
我们改进如下
flag:=10;
while flag>0 do
begin
k:=flag-1;
flag:=0;
for i:=1 to k do
if a[i]<a[i+1] then
begin
temp:=a[i];
a[i]:=a[i+1];
a[i+1]:=temp;
flag:=i;
end;
end;

改进的冒泡算法对上述数据进行的比较次数是19+4+2=24.

l         希尔排序
<1> 基本思想
希尔排序法是1959年由D.L.Shell提出来的,又称减少增量的排序。下表是以八个元素排序示范的例子.在该例中,开始时相隔4个成分,分别按组进行排序,这时每组2个成分,共4组; 然后相隔2个成分,在按组排序......最后,对所有相邻成分进行排序.
可参阅<<计算机程序设计技巧??第三卷排序查找

<2> 算法实现
j:=10;
i:=1;
while j>1 do
begin
j:=j div 2;
repeat
alldone:=true;
for index:=1 to 10-j do
begin
i:=index+j;
if a[index]<a[i] then
begin
temp:=a[index];
a[index]:=a[i];
a[i]:=temp;
alldone:=false;
end;
end;
until alldone
end;
//说句实话,这个很少有人用.:(  当然我也不会,书上抄的
l         插入排序
<1> 基本思想
//对不起,我没书.所以是我自己讲.我很菜．不要介意
插入排序的思想就是读一个，排一个．　　//也许是这样,起码我是这么认为的：）
将第１个数放入数组的第１个元素中，以后读入的数与已存入数组的数进行比较，确定它在从大到小的排列中应处的位置．将该位置以及以后的元素向后推移一个位置，将读入的新数填入空出的位置中．
<2> 算法实现　　｛加了读入语句｝
procedure insert(x,num:integer);
var
i,pos:integer;
search:boolean;
begin
pos:=1;
search:=true;
while search and (pos<=num ) do
if x>a[pos]
then search:=fasle
else inc(pos);
for i:=num downto pos do
a[i+1]:=a[i];
a[pos]:=x;
num:=num+1;
end;
num:=0 {当前数组的长度｝
for i:=1 to 10 do
begin
intert(x,num)
end;

l         合并排序
<1> 基本思想
合并排序的算法就是二分法。
分解：将n个元素分解成各含 一半元素的子序列。
解决：用合并排序法对两个子序列递归地排序。
合并：合并两个已排序的子序列排序结果。
在对子序列排列时，当其长度为1时递归结束，因为单个元素被认为是已排好序的.合并排序的.合并排序的关键步骤在于合并目前产生的两个已排好序的子序列:
A[p..q] 和 A[q+1…r];
将它们合并成一个已排好序的子序列A[p..r]. 我们引入一个辅助过程merge(A,p,q,r)来完成这一项合并工作,其中A是数组,p,q,r是下标.
<2> 算法实现

procedure merge( p,q,r:integer);
var
i,j,t:integer;
it:array[1..10] of integer;
begin
t:=p; i:=p; j:=q+1;
while t<=r do
begin
if (i<=q) and ((j>j) or (a[i]<=a[j]))
then begin
it[t]:=a[i]; inc(i);
end
else begin
it[t]:=a[j]; inc(j);
end;
inc(t);
end;
for i:=p to r do a[i]:=t[i];
end;
procedure merge_sort(p,r:integer);
var q:integer;
begin
if p<>r then begin
q:=(p+r-1) div 2 ;
merge_sort(p,q);
merge_sort(q+1,r);
merge(p,q,r);
end;
end;
begin
merge_sort(1,10);
end.
l         快速排序
<1> 基本思想
快速排序的基本思想是基于分治策略的。对于输入的子序列L[p..r]，如果规模足够小则直接进行排序，否则分三步处理：
分解(Divide)：将输入的序列L[p..r]划分成两个非空子序列L[p..q]和L[q+1..r]，使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。
递归求解(Conquer)：通过递归调用快速排序算法分别对L[p..q]和L[q+1..r]进行排序。
合并(Merge)：由于对分解出的两个子序列的排序是就地进行的，所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序。
这个解决流程是符合分治法的基本步骤的。因此，快速排序法是分治法的经典应用实例之一。
我不太熟悉  请点这里看看Starfish写的   (感谢Starfish 提供)

对于排序的算法我想先做一点简单的介绍，也是给这篇文章理一个提纲。 我将按照算法的复杂度，从简单到难来分析算法。 第一部分是简单排序算法，后面你将看到他们的共同点是算法复杂度为O(N*N)（因为没有使用word,所以无法打出上标和下标）。 第二部分是高级排序算法，复杂度为O(Log2(N))。这里我们只介绍一种算法。另外还有几种 算法因为涉及树与堆的概念，所以这里不于讨论。 第三部分类似动脑筋。这里的两种算法并不是最好的（甚至有最慢的），但是算法本身比较 奇特，值得参考（编程的角度）。同时也可以让我们从另外的角度来认识这个问题。现在，让我们开始吧：

1.冒泡法：

#include <iostream.h>
void BubbleSort(int* pData,int Count)
{
int iTemp;
for(int i=1;i<Count;i++)
{
for(int j=Count-1;j>=i;j--)
{
if(pData[j]<pData[j-1])
{
iTemp = pData[j-1];
pData[j-1] = pData[j];
pData[j] = iTemp;
}
}
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
BubbleSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

2.交换法：

#include <iostream.h>
void ExchangeSort(int* pData,int Count)
{
int iTemp;
for(int i=0;i<Count-1;i++)
{
for(int j=i+1;j<Count;j++)
{
if(pData[j]<pData[i])
{
iTemp = pData[i];
pData[i] = pData[j];
pData[j] = iTemp;
}
}
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
ExchangeSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

3.选择法：

#include <iostream.h>
void SelectSort(int* pData,int Count)
{
int iTemp;
int iPos;
for(int i=0;i<Count-1;i++)
{
iTemp = pData[i];
iPos = i;
for(int j=i+1;j<Count;j++)
{
if(pData[j]<iTemp)
{
iTemp = pData[j];
iPos = j;
}
}
pData[iPos] = pData[i];
pData[i] = iTemp;
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
SelectSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

4.插入法：

#include <iostream.h>
void InsertSort(int* pData,int Count)
{
int iTemp;
int iPos;
for(int i=1;i<Count;i++)
{
iTemp = pData[i];
iPos = i-1;
while((iPos>=0) && (iTemp<pData[iPos]))
{
pData[iPos+1] = pData[iPos];
iPos--;
}
pData[iPos+1] = iTemp;
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
InsertSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

1.快速排序：
#include <iostream.h>
void run(int* pData,int left,int right)
{
int i,j;
int middle,iTemp;
i = left;
j = right;
middle = pData[(left+right)/2]; //求中间值
do{
while((pData[i]<middle) && (i<right))//从左扫描大于中值的数
i++;
while((pData[j]>middle) && (j>left))//从右扫描大于中值的数
j--;
if(i<=j)//找到了一对值
{
//交换
iTemp = pData[i];
pData[i] = pData[j];
pData[j] = iTemp;
i++;
j--;
}
}while(i<=j);//如果两边扫描的下标交错，就停止（完成一次）
//当左边部分有值(left<j)，递归左半边
if(left<j)
run(pData,left,j);
//当右边部分有值(right>i)，递归右半边
if(right>i)
run(pData,i,right);
}
void QuickSort(int* pData,int Count)
{
run(pData,0,Count-1);
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
QuickSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

1.数组的大小是2的幂，这样分下去始终可以被2整除。假设为2的k次方，即k=log2(n)。
2.每次我们选择的值刚好是中间值，这样，数组才可以被等分。

1.双向冒泡：

#include <iostream.h>
void Bubble2Sort(int* pData,int Count)
{
int iTemp;
int left = 1;
int right =Count -1;
int t;
do {
//正向的部分
for(int i=right;i>=left;i--)
{
if(pData[i]<pData[i-1])
{
iTemp = pData[i];
pData[i] = pData[i-1];
pData[i-1] = iTemp;
t = i;
}
}
left = t+1;
//反向的部分
for(i=left;i<right+1;i++)
{
if(pData[i]<pData[i-1])
{
iTemp = pData[i];
pData[i] = pData[i-1];
pData[i-1] = iTemp;
t = i;
}
}
right = t-1;
}while(left<=right);
}
void main()
{
int data[] = {10,9,8,7,6,5,4};
Bubble2Sort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}
2.SHELL排序

#include <iostream.h>
void ShellSort(int* pData,int Count)
{
int step[4];
step[0] = 9;
step[1] = 5;
step[2] = 3;
step[3] = 1;
int i,Temp;
int k,s,w;
for(int i=0;i<4;i++)
{
k = step[i];
s = -k;
for(int j=k;j<Count;j++)
{
iTemp = pData[j];
w = j-k;//求上step个元素的下标
if(s ==0)
{
s = -k;
s++;
pData[s] = iTemp;
}
while((iTemp<pData[w]) && (w>=0) && (w<=Count))
{
pData[w+k] = pData[w];
w = w-k;
}
pData[w+k] = iTemp;
}
}
}
void main()
{
int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1};
ShellSort(data,12);
for (int i=0;i<12;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

• 收藏
• 评论
• 举报

0/200