黑马IOS培训期待与您交流!
常用的数据结构之排序算法
/*插入排序*/
BiInsertsort(int r[], int n) //插入排序(折半)
{
for(int i=2;i<=n;i++)
{
if (r[i]<r[i-1])
{
r[0] = r[i]; //设置哨兵
int low=1,high=i-1; //折半查找
while (low<=high)
{
int mid=(low+high)/2;
if (r[0]<r[mid])
{ high=mid-1};
else
{low = mid+1;}
}
int j;
for (j=i-1;j>high;j--) r[j+1] = r[j]; //后移
r[j+1] = r[0];
}
}
for(int k=1;k<=n;k++) printf(“%d”,r[k]);
printf(“\n”);
}
//希尔排序
void ShellSort ( int r[], int n) {
for(int d=n/2;d>=1;d=d/2) //以d为增量进行直接插入排序
{
for (int i=d+1;i<=n;i++)
{
r[0] = r[i]; //暂存被插入记录
int j;
for( j=i-d; j>0 && r[0]<r[j]; j=j-d) r[j+d] = r[j]; //记录后移d个位置
r[j+d] = r[0];
}
}
for(int i=1;i<=n;i++) printf(“%d”,r[k]);
printf(“\n”);
}
//起泡排序
void BubbleSort(int r[], int n) {
int temp,exchange,bound;
exchange=n; //第一趟起泡排序的范围是r[0]到r[n-1]
while (exchange) //仅当上一趟排序有记录交换才进行本趟排序
{
bound=exchange;
exchange=0;
for (int j=1; j<bound; j++) //一趟起泡排序
if (r[j]>r[j+1])
{
temp=r[j];
r[j]=r[j+1];
r[j+1]=temp;
exchange=j; //记录每一次发生记录交换的位置
}
}
for(int i=1;i<=n;i++) printf(“%d”,r[k]);
printf(“\n”);
}
int Partition(int r[], int first, int end) //快速排序一次划分
{
int i=first; //初始化
int j=end;
r[0]=r[first];
while (i<j)
{
while (i<j && r[0]<= r[j]) j--; //右侧扫描
r[i]=r[j];
while (i<j && r[i]<= r[0]) i++; //左侧扫描
r[j]=r[i];
}
r[i]=r[0];
return i; //i为轴值记录的最终位置
}
//快速排序
void QuickSort(int r[], int first, int end)
{
if (first<end)
{ //递归结束
int pivot=Partition(r, first, end); //一次划分
QuickSort(r, first, pivot-1);//递归地对左侧子序列进行快速排序
QuickSort(r, pivot+1, end); //递归地对右侧子序列进行快速排序
}
}
//简单选择排序,选择排序的过程为:在桌上的牌中找出最小的一张牌,拿在手中;重复这种操作,直到把所有牌都拿在手中。
void SelectSort(int r[ ], int n) {
int i,j,index,temp;
for (i=1; i<n; i++) //对n个记录进行n-1趟简单选择排序
{
index=i;
for (j=i+1; j<=n; j++) //在无序区中选取最小记录
if (r[j]<r[index]) index=j;
if (index!=i)
{
temp=r[i];
r[i]=r[index];
r[index]=temp;
}
}
for(i=1;i<=n;i++) printf(“%d”,r[k]);
printf(“\n”);
}
本章所有算法的复杂度
————————————————————————————————
算 法 最好情况 平均情况 最坏情况
————————————————————————————————
快速排序 O(NlogN) O(NlogN) O(N2)
归并排序 O(N) O(NlogN) O(NlogN)
基数排序 O(N) O(N) O(N)
线性查找 O(N)
折半查找 O(NlogN)
哈希查找 O(N/M)*
健树查找 O(1)**
————————————————————————————————
和排序算法一样,查找(searching)算法也是计算机科学中研究得最多的问题之一。查找算法和排序算法是有联系的,因为许多查找算法依赖于要查找的数据集的有序程度。
基本的查找算法有以下4种:
顺序查找(sequential searching)
int sequential_search(char *item, int count,char key)
{
register int t;
for(t=0;t<count;t++)
if(key==item[t])
return t;/*找到返回数组下标*/
return -1;/*no math*/
}
设n为总元素量:
顺序查找平均情况下要测试你n/2个元素;
最优情况下只需测试一个元素;
最差情况下要测试完n个元素。
对于无序的数据而言顺序查找是唯一可行的方法。
比较查找(comparison searching)
基数查找(radix searching)
哈希查找(hashing)
下面仍然以一付乱序的牌为例来描述这些算法的工作过程。
顺序查找的过程为:从第一张开始查看每一张牌,直到找到要找的牌。
比较查找(也被称作binarysearching,即折半查找)要求牌已经排好序,其过程为:任意抽一张牌,如果这张牌正是要找的牌,则查找过程结束。如果抽出的这张牌比要找的牌大,则在它前面的牌中重复查找操作;反之,则在它后面的牌中重复查找操作,直到找到要找的牌。
基数查找的过程为:先将牌按点数分成13堆,或者按花色分成4堆。然后找出与要找的牌的点数或花色相同的那一堆牌,再在这堆牌中用任意一种查找算法找到要找的牌。
哈希查找的过程为:
(1)在桌面上留出可以放若干堆牌的空间,并构造一个函数,使其能根据点数和花色将牌映射到特定的堆中(这个函数被称为hashfunction,即哈希函数)。
(2)根据哈希函数将牌分成若干堆。
(3)根据哈希函数找到要找的牌所在的堆,然后在这一堆牌中找到要找的牌。
例如,可以构造这样一个哈希函数:
pile=rank+suit
其中,rank是表示牌的点数的一个数值;suit是表示牌的花色的一个数值;pile表示堆值,它将决定一张牌归入到哪一堆中。如果用1,2,……,13分别表示A,2,…….K,用0,1,2和3分别表示梅花、方块、红桃和黑桃,则pile的值将为1,2,……,16,这样就可以把一付牌分成16堆。
哈希查找虽然看上去有些离谱,但它确实是一种非常实用的查找算法。各种各样的程序,从压缩程序(如Stacker)到磁盘高速缓存程序(如SmartDrive),几乎都通过这种方法来提高查找速度,
以下是一个对字符数组进行对分查找的函数:
/* The Binary search*/
int binary_search(char *items,int count,char key)
{
int low,high,mid;
low=0;high=count-1;
while(low<=high)
{
mid=(low+high)/2;
if(key<items[mid])
high=mid-1;
if(key>items[mid])
low=mid+1;
else
return mid; /*found*/
}
return -1;
}
对分查找的最优情况也是只比较一次;
最差情况下的比较次数为:log2n。