标签:
排序技术有很多种,下面简单介绍一下几种。
一 插入排序
1.1 直接插入排序
基本思想:每次将一个待排序额记录按其关键码的大小插入到一个已经排好序的有序序列中,直到全部记录排好序。
图解:
代码实现:
- void InsertSort(int r[], int n)
- {
- for (int i=2; i<n; i++)
- {
- r[0]=r[i];
- for (int j=i-1; r[0]<r[j]; j--)
- r[j+1]=r[j];
- r[j+1]=r[0];
- }
- for(int k=1;k<n;k++)
- cout<<r[k]<<" ";
- cout<<"\n";
- }
1.2 希尔排序
基本思想是: 先将整个待排序记录序列分割成若干个子序列,在在序列内分别进行直接插入排序,待整个序列基本有序时,再对全体记录进行一次直接插入排序。
图解:
代码实现:
- <span style="font-size:14px;">
- void ShellSort(int r[], int n)
- {
- int i;
- int d;
- int j;
- for (d=n/2; d>=1; d=d/2)
- {
- for (i=d+1; i<n; i++)
- {
- r[0]=r[i];
- for (j=i-d; j>0 && r[0]<r[j]; j=j-d)
- r[j+d]=r[j];
- r[j+d]=r[0];
- }
- }
- for(i=1;i<n;i++)
- cout<<r[i]<<" ";
- cout<<"\n";
- }</span>
二 交换排序
2.1 起泡排序
起泡排序是交换排序中最简单的排序方法,其基本思想是: 两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。
图解:
代码实现:
- <span style="font-size:14px;">
- void BubbleSort(int r[], int n)
- {
- int temp;
- int exchange;
- int bound;
- exchange=n-1;
- while (exchange)
- {
- bound=exchange;
- exchange=0;
- for (int j=0; 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=0;i<n;i++)
- cout<<r[i]<<" ";
- cout<<"\n";
- }</span>
2.2快速排序
基本思想:通过一趟
排序将要排序的
数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以
递归进行,以此达到整个数据变成有序序列。
图解:
代码实现:
- int Partition(int r[], int first, int end)
- {
- int i=first;
- int j=end;
- int temp;
-
- while (i<j)
- {
- while (i<j && r[i]<= r[j])
- j--;
- if (i<j)
- {
- temp=r[i];
- r[i]=r[j];
- r[j]=temp;
- i++;
- }
- while (i<j && r[i]<= r[j])
- i++;
- if (i<j)
- {
- temp=r[j];
- r[j]=r[i];
- r[i]=temp;
- j--;
- }
- }
- return 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);
- }
-
- }
三 选择排序
3.1 简单选择排序
基本思想:设所排序序列的记录个数为n。i取1,2,…,n-1,从所有n-i+1个记录(Ri,Ri+1,…,Rn)中找出排序码最小的记录,与第i个记录交换。执行n-1趟
后就完成了记录序列的排序。
图解:
代码实现:
- void SelectSort(int r[ ], int n)
- {
- int i;
- int j;
- int index;
- int temp;
- for (i=0; i<n-1; i++)
- {
- 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=0;i<n;i++)
- cout<<r[i]<<" ";
- cout<<"\n";
- }
3.2 堆排序
堆的定义
堆是具有下列性质的完全二叉树:每个结点的值都小于或等于其左右孩子结点的值(小根堆);或者每个结点的值都大于或等于其左右孩子结点的值(大根堆)。
大根堆和小根堆:根结点(亦称为堆顶)的
关键字是堆里所有结点关键字中最小者的堆称为小根堆,又称
最小堆。根结点(亦称为堆顶)的
关键字是堆里所有结点关键字中最大者,称为大根堆,又称最大堆。注意:①堆中任一子树亦是堆。②以上讨论的堆实际上是
二叉堆(Binary
Heap),类似地可定义k叉堆。
假设当前要筛选结点的编号为k,堆中最后一个结点的编号为m,并且结点k的左右子树均是堆(即r[k+1] ~ r[m]满足堆的条件),则筛选算法用伪代码可描述为:
具体的筛选代码如下:
- void Sift(int r[], int k, int m)
- {
-
- int i;
- int j;
- int temp;
- i=k;
- j=2*i+1;
- while (j<=m)
- {
- if (j<m && r[j]<r[j+1])
- j++;
- if (r[i]>r[j]) break;
- else
- {
- temp=r[i];
- r[i]=r[j];
- r[j]=temp;
- i=j;
- j=2*i+1;
- }
- }
- }
堆排序
堆排序的基本思想是:首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录,然后将它从堆中移走(通常将堆顶记录和堆中最后一个记录交换),并将剩余的记录再调整成堆,这样又找出了次大的记录,以此类推,直到堆中只有一个记录为止。
(1)用大根堆排序的基本思想
① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
……
直到无序区只有一个元素为止。
(2)大根堆排序算法的基本操作:
① 初始化操作:将R[1..n]构造为初始堆;
② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
注意:
①只需做n-1趟排序,选出较大的n-1个
关键字即可以使得文件递增有序。
②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接
选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止
代码实现:
- void HeapSort(int r[ ], int n)
- {
-
- int i;
- int temp;
- for (i=n/2; i>=0; i--)
- Sift(r, i, n) ;
- for (i=n-1; i>0; i--)
- {
- temp=r[i];
- r[i]=r[0];
- r[0]=temp;
- Sift(r, 0, i-1);
- }
- for(i=0;i<n;i++)
- cout<<r[i]<<" ";
- cout<<"\n";
- }
四 归并排序
二路归并排序
基本思想:将若干个有序序列进行两两归并,直至所有待排序记录都在一个有序序列为止。
一路归并算法实现:
- void Merge(int r[], int r1[], int s, int m, int t)
- {
-
- int i=s;
- int j=m+1;
- int k=s;
-
- while (i<=m && j<=t)
- {
- if (r[i]<=r[j])
- r1[k++]=r[i++];
- else
- r1[k++]=r[j++];
- }
- if (i<=m)
- while (i<=m)
- r1[k++]=r[i++];
- else
- while (j<=t)
- r1[k++]=r[j++];
- }
- void MergePass(int r[ ], int r1[ ], int n, int h)
- {
- int i=0;
- int k;
-
- while (i<=n-2*h)
- {
- Merge(r, r1, i, i+h-1, i+2*h-1);
- i+=2*h;
- }
- if (i<n-h)
- Merge(r, r1, i, i+h-1, n);
- else for (k=i; k<=n; k++)
- r1[k]=r[k];
- }
-
- void MergeSort1(int r[ ], int r1[ ], int n )
- {
- int h=1;
- int i;
-
- while (h<n)
- {
- MergePass(r, r1, n-1, h);
- h=2*h;
- MergePass(r1, r, n-1, h);
- h=2*h;
- }
- for(i=0;i<n;i++)
- cout<<r[i]<<" ";
- cout<<"\n";
- }
下面看看二路归并排序的递归实现
- void MergeSort2(int r[], int r1[], int r2[],int s, int t)
- {
-
- int m;
- if (s==t)
- {
- r1[s]=r[s];
-
- }
- else
- {
- m=(s+t)/2;
- MergeSort2(r, r2, r1, s, m);
- MergeSort2(r, r2, r1, m+1, t);
- Merge(r2, r1, s, m, t);
- }
- }
总结
各种排序方法的比较(未完待续):
排序算法(简)
标签:
原文地址:http://www.cnblogs.com/NullPointException/p/5075300.html