数据结构算法
在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的;若具有相同关键字的记录之间的相对次序发生改变,则称这种排序方法是不稳定的。即所有相等的数经过某种排序方法后,仍能保持它们在排序之前的相对次序,则说这种排序算法是稳定的,反之,就是不稳定的。
、
一、冒泡排序
冒泡排序(BubbleSort)的基本概念是:
个人理解就是将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮。在冒泡排序算法中我们要对这个“气泡”序列处理若干遍。所谓一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻的元素的顺序是否正确。如果发现两个相邻元素的顺序不对,即“轻”的元素在下面,就交换它们的位置。显然,处理一遍之后,“最轻”的元素就浮到了最高位置;处理二遍之后,“次轻”的元素就浮到了次高位置。在作第二遍处理时,由于最高位置上的元素已是“最轻”元素,所以不必检查。一般地,第i遍处理时,不必检查第i高位置以上的元素,因为经过前面i-1遍的处理,它们已正确地排好序。
代码实现如下:
1 #include"iostream" 2 void insert(int *p,int num) 3 { 4 //大到小排序 5 int i,j,temp; 6 for(i=0;i<num;i++) 7 for(j=i;j<num;j++) 8 if(p[i]<p[j+1]) 9 { 10 temp=p[i]; 11 p[i]=p[j+1]; 12 p[j+1]=temp; 13 } 14 for(i=0;i<num;i++) 15 { 16 std::cout<<"p["<<i+1<<"] "<<p[i]<<" "; 17 } 18 19 } 20 int main() 21 { 22 23 int a[6]={3,9,5,19,1,17}; 24 insert(a,6); 25 system("pause"); 26 return 0; 27 }
运行截图:
二、插入排序
插入排序主要思想是:把要排序的数字插入到已经排好的数据中。(我自己理
解的哈)。例如12356是已经排好的序,我们将4插入到他们中,时插入之后也是排好序的。这里显而易见是插入到3的后面。变为123456.
实现思路:插入排序就是先是一个有序的数据,然后把要插入的数据插到指定的位置,而排序首先给的就是无序的,我们怎么确定先得到一个有序的数据呢?答案就是:如果只有一个,当然是有序的咯。我们先拿一个出来,他是有序的,然后把数据一个一个插入到其中,那么插入之后是有序的,所以直到最后都是有序的。
主要代码如下:
1 #include"iostream" 2 void sort(int *p,int num) 3 { 4 //大到小排序 5 int i,j,temp; 6 for(i=0;i<num;i++) 7 for(j=i;j<num;j++) 8 if(p[i]<p[j+1]) 9 { 10 temp=p[i]; 11 p[i]=p[j+1]; 12 p[j+1]=temp; 13 } 14 for(i=0;i<num;i++) 15 { 16 std::cout<<" p["<<i+1<<"] "<<p[i]<<" "; 17 } 18 std::cout<<std::endl; 19 } 20 void insert(int *p,int n,int m) 21 { 22 int i,j,temp; 23 for(i=0;i<n;i++) 24 for(j=i;j<n;j++) 25 if(p[i]<p[j+1]) 26 { 27 temp=p[i]; 28 p[i]=p[j+1]; 29 p[j+1]=temp; 30 } 31 for(i=0;i<n;i++) 32 if(m<p[i]&&p[i+1]<m) 33 { 34 for(int j=n;j>i;j--) 35 { 36 p[j+1]=p[j]; 37 } 38 p[i+1]=m; 39 40 } 41 for(i=0;i<=n;i++) 42 { 43 std::cout<<" p["<<i+1<<"] "<<p[i]<<" "; 44 } 45 } 46 int main() 47 { 48 49 int a[6]={3,9,5,19,1,17}; 50 std::cout<<" 排序之前的:"<<std::endl; 51 for(int i=0;i<6;i++) 52 { 53 std::cout<<" p["<<i+1<<"] "<<a[i]<<" "; 54 } 55 std::cout<<std::endl<<"\n 排序之后的:"<<std::endl; 56 sort(a,6); 57 std::cout<<"\n 插入数字后:"<<std::endl; 58 insert(a,6,8); 59 system("pause"); 60 return 0; 61 }
运行截图:
三、合并排序
合并的含义就是将两个或两个以上的有序数据序列合并成一个新的有序数据序列,因此它又叫归并算法。它的基本思想就是假设数组A有N个元素,那么可以看成数组A是又N个有序的子序列组成,每个子序列的长度为1,然后再两两合并,得到了一个 N/2 个长度为2或1的有序子序列,再两两合并,如此重复,值得得到一个长度为N的有序数据序列为止,这种排序方法称为2—路合并排序。
例如数组A有7个数据,分别是: 49 38 65 97 76 13 27,那么采用归并排序算法的操作过程如图7所示:
初始值 [49] [38] [65] [97] [76] [13] [27]
看成由长度为1的7个子序列组成
第一次合并之后 [38 49] [65 97] [13 76] [27]
看成由长度为1或2的4个子序列组成
第二次合并之后 [38 49 65 97] [13 27 76]
看成由长度为4或3的2个子序列组成
第三次合并之后 [13 27 38 49 65 76 97]
合并算法的核心操作就是将一维数组中前后相邻的两个两个有序序列合并成一个有序序列。合并算法也可以采用递归算法来实现,形式上较为简单,但实用性很差。合并算法的合并次数是一个非常重要的量,根据计算当数组中有3到4个元素时,合并次数是2次,当有5到8个元素时,合并次数是3次,当有9到16个元素时,合并次数是4次,按照这一规律,当有N个子序列时可以推断出合并的次数是X(2 >=N,符合此条件的最小那个X)。
代码如下:
1 #include"iostream" 2 void mergesort(int *a,int nstart,int mid,int nend) 3 { 4 mid=(nstart+nend)/2; 5 int n1=mid-nstart+1; 6 int n2=nend-mid; 7 int *a1=new int[n1]; 8 int *a2=new int[n2]; 9 int p=0,q=0; 10 //if(nstart<nend) 11 { 12 for(int i=nstart;i<n1;i++) 13 { 14 a1[p++]=a[i]; //a1存放前面一半的数 //存放前一个数 15 //a1++; 16 } 17 for(int j=mid;j<n2;j++) 18 { 19 a2[q++]=a[j]; //a2存放后面一半的数 //存放后一个数 20 //a2++; 21 } 22 int m=0,n=0,k=0; 23 for(;n<n1&&m<n2;n++,m++)//合并a1、a2的数字(a1中保存的数字与a2保存的数字的个数相同) 24 { 25 if(a1[n]<a2[m])//大数放前,小数放后 26 a[k]=a2[m]; 27 else 28 { 29 a[k]=a1[n]; 30 } 31 k++; 32 } 33 while(n<n1)//合并剩下的数字 34 a[k++]=a1[n++]; 35 while(m<n2) 36 a[k++]=a2[m++]; 37 } 38 } 39 void merge(int *a,int nstart,int nend) //递归使用 40 { 41 int mid=(nstart+nend)/2; 42 int n1=mid-nstart+1; 43 int n2=nend-mid; 44 if(nstart<nend) 45 46 { 47 merge(a,nstart,mid); 48 merge(a,mid+1,nend); 49 mergesort(a,nstart,mid,nend); 50 } 51 } 52 53 int main() 54 { 55 using namespace std; 56 int a[7]={49, 38 ,65, 97, 76, 13, 27}; 57 // int b[5]={2,4,6,8,10}; 58 cout<<"未合并之前的顺序:"<<endl; 59 for(int i=0;i<7;i++) 60 { 61 cout<<"a["<<i<<"] "<<a[i]<<" "; 62 } 63 cout<<std::endl; 64 merge(a,0,7); 65 cout<<"合并之后的顺序:"<<endl; 66 for(int i=0;i<7;i++) 67 { 68 cout<<"a["<<i<<"] "<<a[i]<<" "; 69 } 70 cout<<std::endl; 71 system("pause"); 72 73 74 }