回顾大学--大二数据结构实验--实验二 排序算法

写在前面的话:

假期的时候写了一些关于大学的一些积累,想开学后时间充裕的话继续完成下去,没想到大三下学期还是很忙,实验、项目和比赛占据了我的大部分时间,所以一直耽搁了。现在想挤出来时间继续写下去,不能有大块的时间,但是可以一篇文章分几次写,只要不搁置了这个博客就行,算是一种个人积累吧。

——————————————————————————————————————————————————————————————————

一、实验目的

掌握各种排序方法的实现思想。

二、实验内容

1、创建排序类。

2、提供操作:选择排序、冒泡排序、插入排序、基数排序、快速排序、归并排序。(快速排序、归并排序讲到之后再做)

3、*能够显示各种排序算法的中间过程。


——————————————————————————————————————————————————————————————————

下面是我的代码:    点此下载排序算法演示

——————————————————————————————————————————————————————————————————


这里要求创建排序类,就用类的方式来表示吧(能看懂的完全可以转换成c的代码):

0,排序类定义 Sort.h 的内容为:

class Sort
{
public:
	Sort(int *array,int num);
	//the sort method
	void BubbleSort();
	void RadixSort();
	void SelectSort();
	void InsertSort();
	//print the sorted array
	void Output();
private:
	int *a;//the array to be sorted
	int n;//the length of the array a
};


然后是在Sort.cpp中的实现:

1,构造方法:

Sort::Sort(int *array,int num)
{
	n=num;
	a=new int[n];
	for(int i=0;i<n;i++)
	{
            a[i]=array[i];
	}
}

将传入的数组拷贝到Sort内部的数组a中,也就是排内部数组,不是将传入数组排序。其实怎么样实现都无所谓了,具体看排序算法吧。

2,选择排序算法:

void Sort::SelectSort()
{
	for(int i=0;i<n-1;i++)//总共n个,只需要排n-1个即可
	{  
            int small=i;
            for(int j=i+1;j<n;j++)  //从剩下的第i+1到n-1个里挑最小的
            {  
                if(a[small]>a[j])  
                    small=j;
            }
	    Output();//这个是输出一下数组内容,可以看到单步排序的过程
            swap(a[i],a[small]);//将最小的那个排到队列的后面,这时0-i是已经排好的序列
        }
	Output();
}


a)思想:

首先明确我的排序是排成从小到大的升序。所以选择排序的是一种很自然的排序思想——每次选一个最小的来排。也就是第一次选一个最小的a1放在要输出的序列里,第二次选剩下最小的a2放在序列最后面,现在序列就变成a1,a2了。依次选最小的放序列最后面即可。

类似现在有一堆小孩,要从小个到大个排队。首先找出最矮个的小孩a1站在排头,然后挑剩下一堆小孩最矮的a2再站在a1的后面。依次就排好了。

b)复杂度分析:

i=0时,从0~n-1个里找最小的,需要n-1次比较,参看第4行的for循环,从1到n-1,所以共n-1次

i=1时,从1~n-1个里找最小的,需要n-2次比较

……

i=n-2时,需要n-1到n-1共1次比较

总计:(n-1)+(n-2)+...+1 = (n-1)*n/2

复杂度为O(n²)


c)排序过程:

Select Sort:
5 4 3 2 1
1 4 3 2 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5


3,冒泡排序

这个排序在学完之后,同学们在说起排序的时候都会想到冒泡排序,可能原因是这个名字比较好吧,当然前提是它相对简单。

void Sort::BubbleSort()
{
    for(int i=0;i<n-1;i++)  //总共n个,只需要排n-1个即可
    {  
	//将最小的冒泡到前面去,因为前面已经是排好的,所以只能冒到第i个
        for(int j=n-1;j>i;j--)  
        {  
            Output();//这个是输出一下数组内容,可以看到单步排序的过程
            if(a[j]<a[j-1])  
                swap(a[j],a[j-1]);  
        }  
    }  
    Output();
}

a)思想:

我实现的冒泡排序是两两比较,然后将最小的冒到前面。如第1个和第2个比较,如果第1个比第2个大,那么第2个就冒到第1个前面。

还是例如一排小孩要按照高矮个排序,矮个子的要排在前面。

选择排序的方法是:

放眼望去,自己找出最矮的拎到最前面去。第二步是在剩下找最矮的放到第二。。。一直到最后排序完成。

冒泡排序的方法是:

从最后一个小孩开始,他看看自己是不是比前面的矮,是比前面的矮的话就跟他换一下位置。这样倒数第1的小孩现在是倒数第2了。

然后是倒数第2的小孩看看自己是不是比前面的矮,是比前面的矮的话就跟他换一下位置,否则就不换。

然后是倒数第3的小孩。。。最后就完成最矮的肯定在最前面。到这里才算完成选择排序的第一趟。

然后继续冒第二矮的小孩。。。直到最后排序完成。

b)复杂度分析:

i=0时,从0~n-1个里找最小的,需要n-1次比较,参看第5行的for循环,从1到n-1,所以共n-1次

i=1时,从1~n-1个里找最小的,需要n-2次比较

……

i=n-2时,需要n-1到n-1共1次比较

(跟选择排序一模一样,不过移动次数会多一点)

复杂度为O(n²)


c)排序过程:

Bubble Sort:
5 4 3 2 1
5 4 3 1 2
5 4 1 3 2
5 1 4 3 2
1 5 4 3 2
1 5 4 2 3
1 5 2 4 3
1 2 5 4 3
1 2 5 3 4
1 2 3 5 4
1 2 3 4 5


4,插入排序

void Sort::InsertSort()
{
    for(int i=1;i<n;i++)  //总共n个,只需要排n-1个即可
    {  
        //前i-1个是排好的,将第i个插入到合适的位置
        for(int j=i;j>0;j--)  
        {  
            Output();//这个是输出一下数组内容,可以看到单步排序的过程
            if(a[j]<a[j-1])  
                swap(a[j],a[j-1]);  
            else  
                break;
        }  
    }  
    Output();
}


a)思想:

将数据分为两份:排好序的和未排好序的。每次从未排好序的里面选一个插入到排好的序列中。当然要插入到适当位置,使得插入后还是排好序的序列。

由于是插入到已经排好序的序列中,所以就从后到前挨个比较即可,比自己大就与自己交换一下,遇到比自己小的时候,此时一定是找到了自己的合适的位置了。

可以用打扑克时候的插扑克牌来想象即可。

b)复杂度分析:

i=1时,将1号插入到序列中,只需跟0号比较,需要1次比较

i=2时,将2号插入到序列中,最多跟1号和0号比较,需要2次比较

……

i=n-1时,最多需要n-1次比较


复杂度为O(n²)


c)排序过程:

Insert Sort:
5 4 3 2 1
4 5 3 2 1
4 3 5 2 1
3 4 5 2 1
3 4 2 5 1
3 2 4 5 1
2 3 4 5 1
2 3 4 1 5
2 3 1 4 5
2 1 3 4 5
1 2 3 4 5


 排序算法总结:

      特点

名称

时间复杂度

原理

稳定性

举例(3,1,4,5,2)

名次排序

O(n2)

先排出名次,再根据名次,将数据放入相应

的数组排序

稳定

名次是(3,1,4,5,2)

排序是(1,2,3,4,5)

冒泡排序

O(n2)

一次冒泡是从前面开始两两比较,如果前面大

后面数小就互换,共冒n次泡

稳定

一次冒泡:1,3,4,2,5

二次冒泡:1,3,2,4,5

三次冒泡:1,2,3,4,5

四次冒泡:1,2,3,4,5

五次冒泡:1,2,3,4,5

插入排序

O(n2)

第一个数据不动,将第二个与之比较,并插

入,第三个与前两个比较并插入....直到n个

稳定

插入第二个:1,3,4,5,2

插入第三个:1,3,4,5,2

插入第四个:1,3,4,5,2

插入第五个:1,2,3,4,5

选择排序

O(n2)

n个数中选择最大的放在最后,再在前n-1个

选择最大的放在倒数第二个...直到第一个.

稳定

第一次:3,1,4,2,5

第二次:3,1,2,4,5

第三次:1,2,3,4,5

第四次:1,2,3,4,5

基数排序

Θ(n)

按照基数r分为r个盒子,将符合条件的数据

放入相应链表盒子里,直到排序完成

稳定

一次:1,2,3,4,5

堆排序

O(nlogn)

利用最大堆排序,将数据初始化为最大堆,依次

删除最大元素,直到删完,排序完成

不稳定

删除5,删除4,删除3,

删除2,删除1,依次放入链表,

12345

拓扑排序

O(n2)

在由任务建立的有向图中,边(i,j)表示在装配

序列中任务i 在任务j  的前面,具有这种性质

的序列称为拓扑序列根据任务的有向图建立

拓扑序列的过程

稳定

快速排序

平均O(nlog2n)

最坏O(n2)

不断寻找一个序列的中点,然后对中点左右

的序列递归的进行排序,直至全部序列排序

完成,使用了分治的思想

稳定

第一次;1,3,4,5,2

第二次:1,3,4,2,5

第三次:1,2,3,4,5

归并排序

平均O(nlog2n)

最坏O(nlog2n)

将原序列划分为有序的两个序列,然后利用

归并算法进行合并,合并之后即为有序序列。

稳定

3,1  4,5,2

1,3  2,4,5

1, 2, 3 ,4, 5

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值