admin 管理员组文章数量: 887021
2024年2月6日发(作者:简单静态网页制作成品)
C/C++版数据结构之排序算法
今天讨论下数据结构中的排序算法。
排序算法的相关知识:
(1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。
(2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的。相反,如果发生改变,这种排序方法不稳定。
(3)排序算法的分类(分为5类):插入排序、选择排序、交换排序、归并排序和分配排序。
(4)排序算法两个基本操作:<1>比较关键字的大小。
<2>改变指向记录的指针或移动记录本身。
具体的排序方法:
插入排序
<1>插入排序(Insertion Sort)的思想:每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子记录中的适当位置,直到全部记录插入完成为止。
<2>常用的插入排序方法有直接插入排序和希尔排序。
(1)直接插入排序
<1>算法思路:把一个记录集(如一个数组)分成两部分,前半部分是有序区,后半部分是无序区;有序区一开始有一个元素r[0],无序区一开始是从r[1]到之后的所有元素;然后每次从无序区按顺序取一个元素r[i],拿到有序区中由后往前进行比较,每次比较时,有序区中比r[i]大的元素就往后移动一位,直到找到小于r[i]的元素,这时r[i]插到小元素的后面,则完成一趟直接插入排序。如此反复,从无序区不断取元素插入到有序区,直到无序区为空,则插入算法结束。
<2>算法演示:
//直接插入排序:
#include
using namespace std;
void InsertSort(int r[],int n);
int main()
{
int r[]={24,1,56,2,14,58,15,89};
InsertSort(r,8);
for(int i=0;i<8;i++)
{
cout< } cout< return 0; } void InsertSort(int r[],int n) { for(int i=1;i { for(int j=i-1,s=r[i];s { r[j+1]=r[j]; } r[j+1]=s; } } 复制代码 (2)折半插入排序 <1>算法思路:我们看到在直接插入排序算法中,需要在有序区查找比r[i]的小的元素,然后插入到这个元素后面,但这里要注意这个元素是从无序区算第一个比r[i]小的元素。折半插入排序就是在有序区折半查找这个元素。 <2>算法演示: //折半插入排序 #include using namespace std; void BinInsertSort(int r[],int n); int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; BinInsertSort(r,10); for(int i=0;i<10;i++) { cout< } cout< return 0; } void BinInsertSort(int r[],int n) { for(int i=1;i { int s=r[i]; int low=0; int high=i-1; while(low <= high) { int mid=(low+high)/2; if(s < r[mid]) { high=mid-1; } else { low=mid+1; } } for(int j=i-1;j>=high+1;j--) { r[j+1]=r[j]; } r[high+1]=s; //r[high]是要找的元素 } } 复制代码 (3)希尔排序(Shell Sort) <1>算法思路:把整个记录近一个步长step(一般取记录长度的1/2),分成step个组,再分别对每个级进行直接插入排序;然后再把整个记录近一个新的步长(一般取step/2)分成step/2个组,再分别对每个组进行直接插入排序;如此不断的缩小步长,反复分组排 序,直到步长等于1为此(步长为1则不可能再分组,1是元素之间距离的最小值)。可以看出,希尔排序实质是一种分组插入方法。 <2>算法演示: //希尔排序: #include using namespace std; void ShellSort(int r[],int n); int main() { int r[]={24,1,56,2,14,58,15,89}; ShellSort(r,8); for(int i=0;i<8;i++) { cout< } cout< return 0; } void ShellSort(int r[],int n) { int step=n/2; while(step >= 1) { for(int i=step;i { for(int j=i-step,s=r[i];s { r[j+step]=r[j]; } r[j+step]=s; } step/=2; } } 复制代码 选择排序 <1>选择排序的思想:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已经排好的记录最后,直到全部记录排序完毕。 <2>常用的选择排序方法有直接选择排序和堆排序。 (1)直接选择排序 <1>算法思路:把待排序的n个元素看成一个有序区和一个无序区,开始的时候有序区为空,无序区包含了全部n个元素。排序的时候,每次从无序区中选择比较出其中最小一个元素放到有序区中。如此反复操作,无序区中每小一个元素,有序区中就多一个元素,直到无序区的所有元素都转到有序区中。 <2>算法演示: //简单选择排序: #include using namespace std; void SelectSort(int r[],int n); int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; SelectSort(r,10); for(int i=0;i<10;i++) { cout< } cout< return 0; } void SelectSort(int r[],int n) { for(int i=0;i { int small_loc=i; for(int j=i+1;j { if(r[small_loc] > r[j]) { small_loc=j; } } if(small_loc != i) { int temp=r[i]; r[i]=r[small_loc]; r[small_loc]=temp; } } } 复制代码 (2)堆排序 <1>算法思路:大根堆二叉树中的非终端结点的元素值均大于它的左右孩子的值,因此知道堆的最大值是它的根结点。当根结点移出,则重新调整堆后,堆的次大值称为根结点,依次操作,可以得到堆的从大到小的有序序列。这个算法过程就是堆排序。 堆排序有一个建堆、筛选堆、调整堆的过程。 <2>算法演示: //堆排序: #include using namespace std; void HeapAdjust(int r[],int i,int j); void HeapSort(int r[],int n); int main() { int r[]={53,34,76,23,55,28,63,88,34,66}; HeapSort(r,10); for(int i=0;i<10;i++) { cout< } cout< return 0; } void HeapAdjust(int r[],int i,int j) //调整堆 { int child=2*i; int temp=r[i]; //temp临时存放根结点 while(child <= j) //沿大儿子向下调整 { if(child if(temp >= r[child]) break; r[child/2]=r[child]; child=2*child; } r[child/2]=temp; } void HeapSort(int r[],int n) //建堆 { for(int i=(n-1)/2;i>=0;--i) { HeapAdjust(r,i,n-1); //初始建堆 } for(i=n-1;i>0;--i) { //将当前堆顶元素与当前堆尾元素互换 int temp=r[0]; r[0]=r[i]; r[i]=temp; HeapAdjust(r,0,i-1); //将剩下的元素重新调整成堆 } } 复制代码 交换排序 <1>交换排序的思想:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。 <2>常用的交换排序方法有冒泡排序和快速排序。 (1)冒泡排序 <1>算法思路:通过相邻元素的值的大小比较,并交换值较大的(较小的)元素,使得元素从一端移到到另一端,就像水底冒出的气泡一样。 <2>算法演示: //起泡法排序: #include using namespace std; #define N 5 //N为数的总个数 void BubbleSort(int r[],int n); int main() { int i; int a[N];
版权声明:本文标题:数据结构之排序算法详解(含代码) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1707216235h512430.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论