排序;
1、插入排序(直接插入排序和希尔排序)
2、选择排序(直接选择排序和堆排序)
3、交换排序(冒泡排序和快速排序)
4、归并排序
5、基数排序
---------------------
直接插入排序
说明:逐个将后一个数加到前面的排好的序中。在直接插入排序过程中,对其中一个记录的插入排序称为一次
排序;直接插入排序是从第二个记录开始进行的,因此,长度为n的记录序列需要进行n-1次排序才能完成整个
序列的排序。时间复杂度为O(n2)。
void InsertSort(elemtype x[],int n)
/*用直接插入法对x[0]-x[n-1]排序*/
{
int i,j;
elemtype s;
for(i=0;i<n-1;i++)
{
s=x[i+1];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+1]=x[j];
j--;
}
x[j+1]=s;
}
}
---------------------
希尔排序
说明:希尔排序又称缩小增量排序,增量di可以有各种不同的取法,但最后一次排序时的增量必须为1,最简
单可取di+1=di/2(取小)。时间复杂度为O(n(log2n)2)。
void ShellSort(elemtype x[],int n,intd[],int Number)
/*用希尔排序法对记录x[0]-x[n-1]排序,d为增量值数组*/
/*Number为增量值个数,各组内采用直接插入法排序*/
{
int i,j,k,m,Span;
elemtype s;
for(m=0;m<Number;m++)
{
Span=d[m];
for(k=0;k<Span;k++)
{
for(i=k;i<n-1;i+=Span)/*这个for之后的是“组内采用直接插入法排序”*/
{
s=x[i+Span];
j=i;
while(j>-1&&s.key<x[j].key)
{
x[j+Span]=x[j];
j-=Span;
}
x[j+Span]=s;
}
}
}
}
插入排序个人总结(cute):
1. 插入排序,随机来一个数据,给他找一个“暂时适合“的位置,后面到来的数据,可能会抢夺前面人的位置
2. 适合待排序集合不断更新的情况,稳定集合也可以使用此方法
----------------------------
直接选择排序
说明:每次将后面的最小的找出来插入前面的已排好的序中。同理,具有n个记录的序列要做n-1次排序。
时间复杂度为O(n2)。
void SelectSort(elemtype x[],int n)
/*用直接选择排序法对x[0]-x[n-1]排序*/
{
int i,j,Small;
elemtype Temp;
for(i=0;i<n-1;i++)
{
Small=i;
for(j=i+1;j<n;j++)
if(x[j].key<x[Small].key)
Small=j;
if(Small!=i)
{
Temp=x[i];
x[i]=x[Small];
x[Small]=Temp;
}
}
}
-----------------------------
堆排序:
#include<iostream>
#include<algorithm>
using namespace std;
int A[11],heap_size;
void MaxHeapify(int A[],int i)
{
int largest=-1;
int left=2*i;//获取根节点的左孩子
int right=2*i+1;//获取根节点的右孩子
if(left<=heap_size&&A[left]>A[i])
largest=left;
else
largest=i;
if(right<=heap_size&&A[right]>A[largest])
largest=right;
if(largest!=i)//根节点不是最大值则交换后继续递归
{
swap(A[i],A[largest]);
MaxHeapify(A,largest);
}
}
void BuildMaxHeap(int A[])
{
for(int i=10/2;i>=1;i--)
MaxHeapify(A,i);
}
int main()
{
int i;
heap_size=10;
for(i=1;i<11;i++)
cin>>A[i];
BuildMaxHeap(A);
cout<<"建立的最大堆为:";
for(i=1;i<11;i++)
cout<<A[i]<<"-";
cout<<endl;
for(i=10;i>1;i--)
{
swap(A[i],A[1]);
heap_size--;
MaxHeapify(A,1);
}
cout<<"排序后的结果为:";
for(i=1;i<11;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}
选择排序个人总结(cute)
1. 选择排序为每个位置选择适合的数据,当位置选定之后,即不再会移动位置上的数据。
2. 适合待排序集合已经稳定下来,不再添加新数据的情况。
--------------------------
冒泡排序
说明:两个两个比较,将大的往后移。通过第一次冒泡排序,使得待排序的n个记录中关键字最大的记录排到
了序列的最后一个位置上。然后对序列中前n-1个记录进行第二次冒泡排序。。。对于n个记录的序列,共需进
行n次冒泡排序。时间复杂度为O(n2)。
void BubbleSort(elemtype x[],int n)
/*用冒泡排序法对x[0]-x[n-1]排序*/
{
int i,j,flag=1;
elemtype Temp;
for(i=1;i<n&&flag==1;i++)
{
flag=0;
for(j=0;j<n-i;j++)
{
if(x[j].key>x[j+1].key)
{
flag=1;
Temp=x[j];
x[j]=x[j+1];
x[j+1]=Temp;
}
}
}
}
-----------------------------
快速排序
说明:又叫分区交换排序,是对冒泡排序方法的一种改进。时间复杂度为O(nlog2n)。
void QuickSort(elemtype x[],int low,int high)
/*用递归方法对记录x[0]-x[n-1]进行快速排序*/
{
int i,j;
elemtype Temp;
i=low;
j=high;
Temp=x[low];
while(i<j)
{
/*在序列的右端扫描*/
while(i<j&&Temp.key<=x[j].key)j--;
if(i<j)
{
x[i]=x[j];
i++;
}
/*在序列的左端扫描*/
while(i<j&&x[i].key<Temp.key)i++;
if(i<j)
{
x[j]=x[i];
j--;
}
}
x[i]=Temp;
/*对子序列进行快速排序*/
if(low<i-1)QuickSort(x,low,i-1);
if(j+1<high)QuickSort(x,j+1,high);
}
-----------------------------
另快速排序代码
#include <iostream.h>
int data[9] = {54,38,96,23,15,72,60,45,83};
void quick_sort(int data[], int low, int high)
{
int i, j, pivot;
if (low < high)
{
pivot=data[low];
i=low;
j=high;
while(i<j)
{
while (i<j && data[j]>=pivot)
j--;
if(i<j)
data[i++]=data[j]; //将比枢轴记录小的记录移到低端
while (i<j && data[i]<=pivot)
i++;
if(i<j)
data[j--]=data[i]; //将比枢轴记录大的记录移到高端
}
data[i]=pivot; //枢轴记录移到最终位置
quick_sort(data,low,i-1);
quick_sort(data,i+1,high);
}
}
void main()
{
quick_sort(data, 0, 8);
}
下面对这段程序进行分析。“pivot=data[low];”表示将最低端即第一个元素作为枢轴记录,暂存到pivot中去,“while(i<j)”表示当高低指针相遇时循环终止,否则继续。“while (i<j && data[j]>=pivot) j--;”表示从高端(即数组后面)开始搜索,直到搜索到一个比枢轴值小的某个元素,条件“data[j]>=pivot”用的是大于或等于号,可见,在搜索过程中若遇到相等的则跳过并继续搜索,条件“i<j”不可少,因为在搜索过程中,low与high可能相遇,此“i<j”跟外层while的条件“i<j”无关,作用各不相同,外层while的条件“i<j”是判断在进行从高端向低端搜索一趟、从低端向高端搜索一趟之后高低指针是否相遇,而前者却是在单向的搜索过程中为防止高低指针相遇。
当经过“while (i<j && data[j]>=pivot) j--;”的搜索之后,搜索到一个比枢轴小的元素,因为在搜索完之后i、j可能相等,若相等,就没有交换的必要,因此紧接下面设置了一个判断“if(i<j)”,若成立,那么就要将比枢轴记录小的记录移到低端“data[i++]=data[j];”,这里的“data[i++]”表示先使用了data[i]之后才加1,相当于“data[i]=data[j]; i++;”两句的效果。为什么要i++?是因为刚交换的记录肯定比枢轴小,那么紧接下面的语句“while (i<j && data[i]<=pivot)”就少了一次不必要的比较(因为:data[i]<=pivot必定成立,而i<j在前面的if语句中已成立,则“i<j && data[i]<=pivot”必成立,若没有i++,while中的““i<j && data[i]<=pivot””在肯定成立的情况下执行了一次),提高了效率。执行“data[i++]=data[j];”之后,高端的data[j]覆盖了data[i]的值,第一次覆盖时,覆盖的是data[low]的值,因为最开始时,“pivot=data[low];”将最低端即第一个元素作为枢轴记录暂存到pivot中去了,所以不必担心,会丢失信息,由于data[j]的值赋给了data[i],那么data[j]原来的位置j就可以看做一个空白,下一次覆盖时,就将低端的data[i]复制到这个位置。
紧接下来的“while (i<j && data[i]<=pivot) i++;”是从低端向高端搜索,直到找到一个比枢轴大的元素,先进行判断“if(i<j)”,若成立,如前所述,执行“data[j--]=data[i];”就将低端的data[i]复制到上次赋值后空出的j位置。
如此反复,直到外层while的条件不成立,即i==j,即高低指针相遇,表示已经找到了枢轴记录pivot的最终位置i,执行“data[i]=pivot;”于是,枢轴记录移到最终位置。接下来的“quick_sort(data,low,i-1); quick_sort(data,i+1,high);”表示,对被pivot分开的左右子序列进行递归的快速排序。
这便是整个的排序过程,建议各位以此为例,对其他所有的排序源程序进行调试便于深度剖析理解。
交换排序个人总结(cute):
1. 交换排序,适合已经稳定的数据集合。
2.
-------------------------
归并排序
说明:所谓归并排序就是将两个或两个以上的有序数据序列合并成一个有序数据序列的过程。
时间复杂度为O(nlog2n)。
void merge(r,l,m,h,r1,r2)/*r[l,m]及r[m+1,h]分别有序,归并后置于r2中*/
sqlist r,r2;
int l,m,h;
{
int i,j,k;
k=l;/*k是r2的指示器,i、j分别为s1、s2的指示器*/
i=l;
j=m+1;
while(i<=m&&j<=h)
{
if(r[i].key<=r[j].key)
{
r2[k]=r[i];
i++;
}
else
{
r2[k]=r[j];
j++;
}
k++;
}
if(i>m) /*s1结束*/
while(j<=h)
{
r2[k]=r[j];
j++;k++;
}
else
while(i<=m)
{
r2[k]=r[i];
i++;k++;
}
}