当前位置:首页 » 操作系统 » 分治算法排序算法

分治算法排序算法

发布时间: 2022-05-06 16:33:00

‘壹’ 分治法是什么

分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。

分治法的精髓:

分--将问题分解为规模更小的子问题。

治--将这些规模更小的子问题逐个击破。

合--将已解决的子问题合并,最终得出"母"问题的解。

任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。

n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。

而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。

分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

‘贰’ 数据结构 java开发中常用的排序算法有哪些

排序算法有很多,所以在特定情景中使用哪一种算法很重要。为了选择合适的算法,可以按照建议的顺序考虑以下标准:
(1)执行时间
(2)存储空间
(3)编程工作
对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。

主要排序法有:
一、冒泡(Bubble)排序——相邻交换
二、选择排序——每次最小/大排在相应的位置
三、插入排序——将下一个插入已排好的序列中
四、壳(Shell)排序——缩小增量
五、归并排序
六、快速排序
七、堆排序
八、拓扑排序

一、冒泡(Bubble)排序

----------------------------------Code 从小到大排序n个数------------------------------------
void BubbleSortArray()
{
for(int i=1;i<n;i++)
{
for(int j=0;i<n-i;j++)
{
if(a[j]>a[j+1])//比较交换相邻元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n²),适用于排序小列表。

二、选择排序
----------------------------------Code 从小到大排序n个数--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;i<n-1;i++)
{
min_index=i;
for(int j=i+1;j<n;j++)//每次扫描选择最小项
if(arr[j]<arr[min_index]) min_index=j;
if(min_index!=i)//找到最小项交换,即将这一项移到列表中的正确位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n²),适用于排序小的列表。

三、插入排序
--------------------------------------------Code 从小到大排序n个数-------------------------------------
void InsertSortArray()
{
for(int i=1;i<n;i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
{
int temp=arr[i];//temp标记为未排序第一个元素
int j=i-1;
while (j>=0 && arr[j]>temp)/*将temp与已排序元素从小到大比较,寻找temp应插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表
若列表基本有序,则插入排序比冒泡、选择更有效率。

四、壳(Shell)排序——缩小增量排序
-------------------------------------Code 从小到大排序n个数-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr<0;incr--)//增量递减,以增量3,2,1为例
{
for(int L=0;L<(n-1)/incr;L++)//重复分成的每个子列表
{
for(int i=L+incr;i<n;i+=incr)//对每个子列表应用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j>=0&&arr[j]>temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
适用于排序小列表。
效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
壳(Shell)排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃。

五、归并排序
----------------------------------------------Code 从小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low>=high) return;//每个子列表中剩下一个元素时停止
else int mid=(low+high)/2;/*将列表划分成相等的两个子列表,若有奇数个元素,则在左边子列表大于右侧子列表*/
MergeSort(low,mid);//子列表进一步划分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一个数组,用于存放归并的元素
for(int i=low,j=mid+1,k=low;i<=mid && j<=high;k++)/*两个子列表进行排序归并,直到两个子列表中的一个结束*/
{
if (arr[i]<=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j<=high;j++,k++)//如果第二个子列表中仍然有元素,则追加到新列表
B[k]=arr[j];
for( ;i<=mid;i++,k++)//如果在第一个子列表中仍然有元素,则追加到新列表中
B[k]=arr[i];
for(int z=0;z<high-low+1;z++)//将排序的数组B的 所有元素复制到原始数组arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
适用于排序大列表,基于分治法。

六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的算法思想:选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。*/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
int Partition(int [] arr,int low,int high)
{
int pivot=arr[low];//采用子序列的第一个元素作为枢纽元素
while (low < high)
{
//从后往前栽后半部分中寻找第一个小于枢纽元素的元素
while (low < high && arr[high] >= pivot)
{
--high;
}
//将这个比枢纽元素小的元素交换到前半部分
swap(arr[low], arr[high]);
//从前往后在前半部分中寻找第一个大于枢纽元素的元素
while (low <high &&arr [low ]<=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//将这个枢纽元素大的元素交换到后半部分
}
return low ;//返回枢纽元素所在的位置
}
void QuickSort(int [] a,int low,int high)
{
if (low <high )
{
int n=Partition (a ,low ,high );
QuickSort (a ,low ,n );
QuickSort (a ,n +1,high );
}
}
----------------------------------------Code-------------------------------------
平均效率O(nlogn),适用于排序大列表。
此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
基于分治法。

七、堆排序
最大堆:后者任一非终端节点的关键字均大于或等于它的左、右孩子的关键字,此时位于堆顶的节点的关键字是整个序列中最大的。
思想:
(1)令i=l,并令temp= kl ;
(2)计算i的左孩子j=2i+1;
(3)若j<=n-1,则转(4),否则转(6);
(4)比较kj和kj+1,若kj+1>kj,则令j=j+1,否则j不变;
(5)比较temp和kj,若kj>temp,则令ki等于kj,并令i=j,j=2i+1,并转(3),否则转(6)
(6)令ki等于temp,结束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)

{ //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 int I; BuildHeap(R); //将R[1-n]建成初始堆for(i=n;i>1;i--) //对当前无序区R[1..i]进行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //将堆顶和堆中最后一个记录交换 Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质 } } ---------------------------------------Code--------------------------------------

堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。

堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。 堆排序是就地排序,辅助空间为O(1), 它是不稳定的排序方法。

堆排序与直接插入排序的区别:
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。

八、拓扑排序
例 :学生选修课排课先后顺序
拓扑排序:把有向图中各顶点按照它们相互之间的优先关系排列成一个线性序列的过程。
方法:
在有向图中选一个没有前驱的顶点且输出
从图中删除该顶点和所有以它为尾的弧
重复上述两步,直至全部顶点均已输出(拓扑排序成功),或者当图中不存在无前驱的顶点(图中有回路)为止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*输出拓扑排序函数。若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//对各顶点求入度indegree[0....num]
InitStack(thestack);//初始化栈
for(i=0;i<G.num;i++)
Console.WriteLine("结点"+G.vertices[i].data+"的入度为"+indegree[i]);
for(i=0;i<G.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓扑排序输出顺序为:");
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("发生错误,程序结束。");
exit();
}
Console.Write(G.vertices[j].data);
count++;
for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
{
k=p.adjvex;
if (!(--indegree[k]))
Push(G.vertices[k]);
}
}
if (count<G.num)
Cosole.WriteLine("该图有环,出现错误,无法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
算法的时间复杂度O(n+e)。

‘叁’ 分治算法中排序的完整代码

快速排序
#include<windows.h>
#include<time.h>
#include<stdio.h>

#define MAX 10

void InitData(int a[],int len)
{//随机初始化待排序数据
int i;
srand(time(NULL));
for(i=0;i<len;i++) a[i]=rand()%1000;//随机初始化待排序数据
}

void Print(int a[],int from,int to)
{//输出a[from]到a[to]范围内所有数据,并换行
int i;
for(i=0;i<from;i++) printf(" ");//控制对齐,看出解决子问题的顺序
for(i=from;i<=to;i++) printf("%4d",a[i]);
printf("\n");
}

int part(int A[ ], int from, int to)
{int i=from+1, j=to, temp;
while( i<=j){ while(i<=to && A[i]<=A[from]) i++;
while(j>=from && A[j]>A[from]) j--;
if(i<j) {temp=A[i];A[i]=A[j];A[j]=temp;} //A[j]与A[j]交换
}
temp=A[j]; A[j]=A[from]; A[from]=temp;//A[j]与A[from]交换
return j;
}

void QuickSort(int A[ ], int from, int to) //快速排序的分治思想表达
{
if(from<to){ int position=part(A, from, to);
QuickSort(A,from,position-1);
QuickSort(A, position+1, to);
}
Print(A,from,to);
}

void main(void)
{
int A[MAX];
InitData(A,MAX);
Print(A,0,MAX-1);
QuickSort(A,0,MAX-1);
getch();
}

归并排序
#include<windows.h>
#include<stdio.h>

#define MAX 17

void InitData(int a[],int len)
{int i;
for(i=0;i<len;i++) a[i]=rand()%1000;//随机初始化待排序数据
}

void Print(int a[],int from,int to)
{
int i;
for(i=0;i<from;i++) printf(" ");//控制对齐,看出解决子问题的顺序
for(i=from;i<=to;i++) printf("%4d",a[i]);
printf("\n");
}

void Merge(int A[ ], int from, int to)
{
int *t=(int *)malloc(sizeof(int)*(to-from+1));
int i=from, mid=(to+from)/2, j=mid+1,k=0;
if(from>=to) return ;
Merge (A, from, mid);
Merge (A, mid+1, to); /*递归解决2个子问题*/
while(i<=mid && j<=to)
if(A[i]<A[j]) t[k++]=A[i++];
else t[k++]=A[j++];
while(i<=mid) t[k++]=A[i++];
while(j<=to) t[k++]=A[j++];
i=from;k=0;
while(i<=to) A[i++]=t[k++];//合并两个有序子表,即分别A[from~mid],A[mid+1~to];
//if(to-from>0)
Print(A,from,to); //合并子问题之后,将其打印出来
}

void main(void)
{
int a[MAX];
InitData(a,MAX);
Print(a,0,MAX-1);
Merge(a,0,MAX-1);
getch();
}

‘肆’ C++ 分治法排序

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef int* IntPtr;
void Merge(int A[],int p,int q,int r)
{
int M=999999999;
int n1,n2;
n1=q-p+1;
n2=r-q;
IntPtr L,R;
L=new int[n1+1];
R=new int[n2+1];
int i,j,k;
for(i=1;i<=n1;i++)
L[i]=A[p+i-1];
for(j=1;j<=n2;j++)
R[j]=A[q+j];
L[n1+1]=M;
R[n2+1]=M;
i=1;
j=1;

for (k=p;k<=r;k++)
{
if(L[i]<=R[j])
{
A[k]=L[i];
i++;
}
else
{
A[k]=R[j];
j++;
}
}
}

void Mergesort(int A[],int p,int r)
{
int q;
if(p<r)
{
q=(p+r)/2;
Mergesort(A,p,q);
Mergesort(A,q+1,r);
Merge(A,p,q,r);
}
}

void main()
{
int A[10];
srand(time(0));
for (int i=0;i<10;i++)
{
A[i]=rand();
cout<<A[i]<<endl;
}
cout<<endl;
Mergesort(A,0,9);
for (int j=0;j<10;j++)
{

cout<<A[j]<<endl;
}
}
看看怎样

‘伍’ 什么是分治算法

分治法就是将一个复杂的问题分成多个相对简单的独立问题进行求解,并且综合所有简单问题的解可以组成这个复杂问题的解。
例如快速排序算法就是一个分治法的例子。即将一个大的无序序列排序成有序序列,等于将两个无序的子序列排序成有序,且两个子序列之间满足一个序列的元素普遍大于另一个序列中的元素。

‘陆’ java实现几种常见排序算法

下面给你介绍四种常用排序算法:

1、冒泡排序

特点:效率低,实现简单

思想(从小到大排):每一趟将待排序序列中最大元素移到最后,剩下的为新的待排序序列,重复上述步骤直到排完所有元素。这只是冒泡排序的一种,当然也可以从后往前排。

‘柒’ 什么是分治法的合并排序

分治法、是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……
合并排序、是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
都是网络复制来的,别鄙视。以解决问题为根本原则。对你有帮助就好!

‘捌’ 使用分治法解决排序问题。在线等。很急

#include<stdio.h>
voidsort(int*a,intleft,intright)
{
if(left>=right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/
{
return;
}
inti=left;
intj=right;
intkey=a[left];

while(i<j)/*控制在当组内寻找一遍*/
{
while(i<j&&key<=a[j])
/*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升
序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/
{
j--;/*向前寻找*/
}

a[i]=a[j];
/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是
a[left],那么就是给key)*/

while(i<j&&key>=a[i])
/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,
因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/
{
i++;
}

a[j]=a[i];
}

a[i]=key;/*当在当组内找完一遍以后就把中间数key回归*/
sort(a,left,i-1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/
sort(a,i+1,right);/*用同样的方式对分出来的右边的小组进行同上的做法*/
/*当然最后可能会出现很多分左右,直到每一组的i=j为止*/
}

intmain()
{
inti,a[10];
printf("输入10个整数:");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
sort(a,0,9);
printf("排序结果:")
for(i=0;i<10;i++)
printf("%d",a[i]);
return0;
}

‘玖’ java几种基本排序

/**
*冒泡排序
*比较相邻的元素。如果第一个比第二个大,就交换他们两个。
*对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
*针对所有的元素重复以上的步骤,除了最后一个。
*持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
*@paramnumbers需要排序的整型数组
*/
publicstaticvoidbubbleSort(int[]numbers)
{
inttemp=0;
intsize=numbers.length;
for(inti=0;i<size-1;i++)
{
for(intj=0;j<size-1-i;j++)
{
if(numbers[j]>numbers[j+1])//交换两数位置
{
temp=numbers[j];
numbers[j]=numbers[j+1];
numbers[j+1]=temp;
}
}
}
}

快速排序的基本思想:
通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。
/**
*查找出中轴(默认是最低位low)的在numbers数组排序后所在位置
*
*@paramnumbers带查找数组
*@paramlow开始位置
*@paramhigh结束位置
*@return中轴所在位置
*/
publicstaticintgetMiddle(int[]numbers,intlow,inthigh)
{
inttemp=numbers[low];//数组的第一个作为中轴
while(low<high)
{
while(low<high&&numbers[high]>temp)
{
high--;
}
numbers[low]=numbers[high];//比中轴小的记录移到低端
while(low<high&&numbers[low]<temp)
{
low++;
}
numbers[high]=numbers[low];//比中轴大的记录移到高端
}
numbers[low]=temp;//中轴记录到尾
returnlow;//返回中轴的位置
}

递归形式的分治排序算法:
/**
*
*@paramnumbers带排序数组
*@paramlow开始位置
*@paramhigh结束位置
*/
publicstaticvoidquickSort(int[]numbers,intlow,inthigh)
{
if(low<high)
{
intmiddle=getMiddle(numbers,low,high);//将numbers数组进行一分为二
quickSort(numbers,low,middle-1);//对低字段表进行递归排序
quickSort(numbers,middle+1,high);//对高字段表进行递归排序
}

}

热点内容
工业级安卓主板价格怎么样 发布:2024-10-07 14:07:57 浏览:625
编程先乘除 发布:2024-10-07 13:58:45 浏览:268
编译内核时发生循环编译 发布:2024-10-07 13:58:43 浏览:494
当下笔记本电脑什么配置好 发布:2024-10-07 12:57:33 浏览:468
安卓倒车轨迹怎么调 发布:2024-10-07 12:54:47 浏览:913
问道刷道队伍怎么配置 发布:2024-10-07 12:09:17 浏览:324
androidservice使用 发布:2024-10-07 12:00:01 浏览:262
乐视2安卓版本怎么升级 发布:2024-10-07 11:51:11 浏览:696
方舟电脑版怎么进入官方服务器 发布:2024-10-07 11:09:32 浏览:807
百度云快速上传 发布:2024-10-07 10:52:25 浏览:482