排序算法(一)

原创 2016年05月31日 23:27:54

排序分为冒泡排序,选择排序,插入排序,希尔排序,合并排序,快速排序,堆排序等

等,本篇文章我来详细解析冒泡排序,选择排序,直接插入排序。

我们学会一种排序算法,只要是学会这种算法的思想,而不是单纯的记忆代码~~

(一)冒泡排序:

算法思想:通过一趟冒泡排序,将最大的元素放在最后一个位置(假如从小到大排序),

或者将最小的元素放在最后一个位置(假如从大到小排序)。下边我用图来解释这个思想



下边我来给出冒泡排序的代码(从小到大排序):

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
void bottle_sort(int arr[], int len)
{
	int i = 0;
	int j = 0;
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	for (i = 0;i < len - 1;i++)
	{
		for (j = 0;j < len - i - 1;j++)
		{
			
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			
			}
		}
	}
}
int main()
{
	int arr[5] = {5,6,3,2,1};
	int i = 0;
	bottle_sort(arr,5);
	for (i = 0;i < 5;i++)
	{
		printf("%d ",arr[i]);
	}
	system("pause");
	return 0;
}

这段代码是非常正确的代码,可以得到正确的结果。可是如果给出这样一组数据:2,9,8,7,6(同样要求从大到小排序),你还要比较4趟吗??第1趟比较完后,2就排在

最后,这组数据就已经有序了,所以,后边的几趟排序就是浪费时间~~下边我来给出优

化代码:(下边的代码只给出实现部分,测试部分省略)

<pre name="code" class="cpp">void bottle_sort(int arr[], int len)
{
	int i = 0;
	int j = 0;
	int flag = 0;
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	for (i = 0;i < len - 1;i++)
	{
        flag = 0;
		for (j = 0;j < len - i - 1;j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 1;
			}
		}
		if (flag == 0)
		{
			break;
		}
	}
}




这段代码就比前边那段代码好一点,如果我们发现某一趟就没有进行交换,我们就认为

排序结束,退出。具体实现办法:进入外层循环时,我们给flag置一个数,比如置0,如

果进入if语句,就改变flag的值。出了内层循环,如果flag的值还是0,说明内存没有进行

交换,此时外层循环也结束。

怎么感觉冒泡排序写成这样就已经很不错了。。是吗??其实还有改进得到空间,如果

我们记住上一趟最后一次交换的位置,这一趟的交换只需要排序这个位置之前的元素。

下边给出代码:

void bottle_sort(int arr[], int len)
{
	int i = 0;
	int j = 0;
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	int k = len - 1;
	int m = 0;
	for (i = 0;i < len - 1;i++)
	{
		for (j = 0;j < k;j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				m = j;
			}//找到每一趟最后一次交换的位置
		}
		k = m;
	}
}


代码简析:借助临时变量记住最后一次交换的位置,作为内层循环的边界。

要是把第2种和第3种方法结合起来,是不是更好呢~~~这里不给出代码了。
以上代码给出的是对整形数的排序,可是,如果要排序浮点数,排序结构体,是不是又

要再写一个函数~~c语言中的回调函数可以帮我们这么做~~(之前关于回调函数已经整

理过,这里再给出代码~~)

int compare(const void *elem1, const void *elem2)  
{  
    return *(const int *)elem1 - *(const int *)elem2;  
}  
void sort(void *base, unsigned int num,  
 unsigned int byte, int(*cmp)(const void *elem1, const void *elem2))  
{  
    char *pbase = (char *)base;  
    int flag = 0;  
    int i = 0;  
    int j = 0;  
    int k = 0;  
    const void *p1 = NULL;  
    const void *p2 = NULL;  
    for (i = 0;i < num - 1;i++)  
    {  
        flag = 0;  
        for (j = 0;j < num - 1 - i;j++)  
        {  
            p1 = (const void *)(pbase + j*byte);  
            p2 = (const void *)(pbase + (j + 1)*byte);  
            int ret = cmp(p1, p2);  
            if (ret > 0)  
            {  
                for (k = 0;k < byte;k++)  
                {//交换秘诀  
                    pbase[j*byte + k] = pbase[j*byte + k] + pbase[(j + 1)*byte + k];  
                    pbase[(j + 1)*byte + k] = pbase[j*byte + k] - pbase[(j + 1)*byte + k];  
                    pbase[j*byte + k] = pbase[j*byte + k] - pbase[(j + 1)*byte + k];  
                }  
                flag = 1;  
            }  
            if (flag == 0)  
                break;  
        }  
    }  
}  
int main()  
{  
    int(*cmp)(const void *elem1, const void *elem2) = compare;  
    int arr[4] = { 6,7,4,2 };  
    int i = 0;  
    sort(arr,4,4,cmp);  
    for (i = 0;i < 4;i++)  
    {  
        printf("%d ",arr[i]);  
    }  
    system("pause");  
    return 0;  
}  


如果有问题,可以指出哈~~

(二)选择排序

算法思想:选择最大的元素或最小的元素放在它应该出现的位置。这句话你可能并不太

清楚,下边图解:



下边给出实现代码:

void select_sort(int arr[], int len)
{
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	int i = 0;
	int j = 0;
	int min = 0;//保存固定范围的最小值得下标
	for (i = 0;i < len - 1;i++)
	{
		min = i;
		for (j = i + 1;j < len;j++)
		{
			if (arr[j] < arr[min])
			{
				min = j;
			}
		}
		if (i != min)//如果这个位置放的不是最小数,需要交换
		{
			int tmp = arr[i];
			arr[i] = arr[min];
			arr[min] = tmp;
		}
	}
}


i控制的是找到的最小元素放的位置,j控制的是找最小元的范围(图片中 绿色竖线后

边)。

(三)直接插入排序:

算法思想:将要处理的元素放在前边有序元素的合适的位置。图解:



下边给出实现代码:

void insert_sort(int arr[], int len)
{
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	int i = 0;
	int j = 0;
	int tmp = 0;
	int k = 0;
	for (i = 1;i < len;i++)
	{
		tmp = arr[i];
		for (j = i - 1;j >= 0;j--)
		{
			if (arr[j] <= arr[i])
				break;
		}
		for (k = i - 1;k > j;k--)
		{
			arr[k + 1] = arr[k];
		}
		arr[j+1] = tmp;
	}
}


tmp用来存储需要处理的数。内层第一个循环的作用是找出合适的位置,即就是找到比

当前要处理的元素小的第一个位置。(假设从小到大排序)。内层第二个循环的作用是

移动,将内层循环1找到的位置的下一个位置到要处理元素的位置之间的数据统一后移

一个,然后将要处理的元素放在内层循环1找到的位置的下一个位置。我们仔细看一下

就会发现内层的循环之间好像有一定的联系,能不能把两个循环合成一个呢~~

void insert_sort(int arr[], int len)
{
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	int i = 0;
	int j = 0;
	int tmp = 0;
	for (i = 1;i < len;i++)
	{
		tmp = arr[i];
		for (j = i-1;(j >= 0) && (arr[j]>tmp);j--)//当要处理的元素比前边的元素小并且j还是大于等于0,
			//就要发生移位
		{
			arr[j+1] = arr[j];
		}//循环结束,j下标的元素是刚好小于要处理的元素(不满足arr[j]>tmp)或者是j=-1(不满足j>=0)
		arr[j + 1] = tmp;//将要处理的元素放在上次j的下一个位置
	}
}


其实在移位的环节,我们可以用交换来实现。给出一个简单的例子:比如2要放在3,4的

前边,即就是2与4交换,2再与3交换。下边我来用代码实现以下:

void insert_sort(int arr[], int len)
{
	if (len <= 0)
	{
		printf("数组长度不合理\n");
		exit(EXIT_FAILURE);
	}
	int i = 0;
	int j = 0;
	int tmp = 0;
	int m = 0;
	for (i = 1;i < len;i++)
	{
		tmp = arr[i];
		for (j = i - 1;(j >= 0) && (arr[j]>tmp);j--)
		{
			m = arr[j];
			arr[j] = arr[j + 1];
			arr[j + 1] = m;
		}
	}
}


上边这段代码,是用交换代替移位。下边我再给出图解,方便读者理解。



关于排序先整理这么多,之后再整理出其他的排序方法。以上如有不合理的地方,希望

指出~~


版权声明:本文为博主原创文章,可以转载,但是转载时必须在文首注明原文链接。

相关文章推荐

排序算法ppt

  • 2017年11月03日 20:37
  • 1.37MB
  • 下载

排序算法比较 C实现

  • 2017年06月16日 12:34
  • 413KB
  • 下载

C++ 归并排序算法的实现与改进(含笔试面试题)

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,即把待排序序列分为若干个子序列,每个子序列是有序...

java各自排序算法的实现

  • 2015年06月16日 16:27
  • 3KB
  • 下载

各种排序算法

  • 2015年04月27日 10:09
  • 197KB
  • 下载

常用排序算法时间复杂度和空间复杂度

摘自维基百科: http://zh.wikipedia.org/wiki/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95#.E7.A8.B3.E5.AE.9A.E6.80.A...
  • xiexievv
  • xiexievv
  • 2015年05月17日 20:50
  • 10055

常用排序算法复杂度

  • 2017年09月22日 16:11
  • 16KB
  • 下载

快速排序算法

  • 2015年05月01日 16:41
  • 1KB
  • 下载

冒泡排序算法详解C++程序

冒泡排序算法:(Bubble Sort)首先肯定是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。 用C++实现冒泡算法...

应用于实时性的插入排序算法

  • 2017年09月07日 14:57
  • 174KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:排序算法(一)
举报原因:
原因补充:

(最多只允许输入30个字)