快速排序算法及其应用

news/2024/5/19 21:45:27 标签: 快速排序, 排序算法, 算法

常见的算法>排序算法

冒泡排序,简单排序,插入排序等算法时间复杂度为 n^2,在某些场景下如已知有序的数组中进行排序,调用这些算法可以有效地完成排序功能。

其源码如下:

/************************************************
* title     : 交换
* 算法复杂度 : 	
************************************************/
void swap(SqList *L,int i,int j)
{
	int temp = L->r[i];
	L->r[i] = L->r[j];
	L->r[j] = temp;
}

/************************************************
* title     : 冒泡排序
* 算法复杂度 : 	n^2  时间复杂度
************************************************/
void BubbleSort(SqList *L)
{
	int i,j;
	bool flag = true;
	for(i = 1;i < L->length && flag;i++)
	{
		flag = false;
		for(j = L->length-1;j >= i;j--)
		{
			if(L->r[j] > L-r[j+1])
			{
				swap(L,j,j+1);
				flag = true; /*已知有序可减少遍历次数*/
			}
		}
	}
}

/************************************************
* title     : 简单选择排序
* 算法复杂度 : 	n^2  时间复杂度 但排序性能略优于冒泡
************************************************/
void SelectSort(SqList *L)
{
	int i,j,min;
	for(i = 1;i < L->length;i++)
	{
		min = i;
		for(j = i + 1;j <= L->length;j++)
		{
			if(L->r[min]>L->r[j])
				min = j;
		}
		if(i != min)
		{
			swap(L,i,min);
		}
	}
}

/************************************************
 * title     : 直接插入排序
 * 算法复杂度 : 	n^2  时间复杂度 适用于已经有序数组
 * 的插入√
************************************************/
void InsertSort(SqList *L)
{
	int i,j;
	for(i = 2;i <= L->length;i++)
	{
		if(L->r[i] < L->r[i - 1])
		{
			L->r[0] = L->r[i]; // 设置哨兵
			for(j = i - 1;L->r[j] > L->r[0] ;j--) //遍历,直到找到比哨兵小的值,退出
			{
				L->r[j + 1] = L->r[j];
			}
			L->r[j + 1] = L->r[0];
		}
	}
}

快速排序算法

快速排序算法分为三步:

  • 找基准数,为了方便我们将基准数设置为数组中第一个数。
  • 从待排序的数组的头和尾放两个指针,从尾往前遍历,寻找小于基准数的成员,与基准数交换值,此时基准数位于尾指针处。在从头指针向后遍历,寻找大于基准数的成员,与基准数交换值,此时基准数位于头指针处。重复这个步骤,直到头尾指针重叠,以基准数为枢轴,所以小于基准数的都在左边,所有大于基准数的都在右边。
  • 对枢轴左边和右边区域重复1 2步骤,直到所有区间排序完成。

具体代码如下:

/*对顺序表进行快速排序*/
void QuickSort(SqList *L)
{
	QSort(L,1,L->length);
}

void QSort(SqList *L,int low,int high)
{
	int pivot;
	if(low < high)
	{
		pivot = Partition(L,low,high);

		QSort(L,low,pivot-1);   //对低子表递归排序
		QSort(L,pivot+1,high);  //对高子表递归排序
	}
}

int Partition(SqList *L,int low,int high)
{
	int pivotkey;
	pivotkey = L->r[low]; //用子表的第一个记录作为枢轴

	while (low < high)
	{
		while(low < high && L->r[high] >= pivotkey)
		{
			high--;
		}
		swap(L,low,high);

		while(low < high && L->r[low] <= pivotkey)
		{
			low++;
		}
		swap(L,low,high);
	}
	return low; // pivotkey location
}

快速排序算法复杂度从 n*logn 到 n^2,对应着最优情况到最差情况。
上面代码中我们的基准数选取是选取数组第一个,可以通过优化基准数的选取从而优化算法
基准数的选取可以从待排序数组中,随机选取三个数,然后以这三个数中间大小的数作为基准数。这里就不做演示了。

快速排序的应用

快速排序的应用,也可以理解为对算法>排序算法的应用,这里有一个场景,我们要对采集的编码器数据做低通滤波,要求是用滑动平均窗滤波算法实现。具体代码如下:

/*******************************************************************************
* Function Name  : MySqListAdd
* Description    : 往缓冲区填入数据,直到填满在从头开始
* Input          : L  缓冲区结构体
                   data 填入缓冲区的数据
* Output         : None
* Return         : false 缓冲区还未填满
                   true  缓冲区已经填满
*******************************************************************************/
static bool MySqListAdd(SqList *L , QuickSortElem data)
{
    static uint8_t tmp = 1;
    if(L->length < MAXSIZE)
    {
        L->r[tmp] = data;
        tmp++;
        L->length++;
        
        return false;
        
    } else if(L->length == MAXSIZE) {
        
        tmp = (tmp > MAXSIZE) ? 1 : tmp++;
        L->r[tmp] = data;
        
        return true;
        
    }
    
    return false;
    
}

/*******************************************************************************
* Function Name  : MySqListMovingAverageWindowFilter
* Description    : 滑动平均窗滤波函数
* Input          : L  缓冲区结构体
* Output         : None
* Return         : 0 表示数据还没填充完成
                   else 滤波后的结果
*******************************************************************************/
QuickSortElem MySqListMovingAverageWindowFilter(SqList *L , QuickSortElem data)
{
    uint8_t tmp;
    int32_t sum;
    if(MySqListAdd(L,data))
    {
        
        QuickSort(L);
        
        for(tmp = 2;tmp < MAXSIZE;tmp++)
        {
            sum += L->r[tmp];
        }
        sum = sum / (MAXSIZE - 2);
        
        return sum;
        
    }
    
    return 0;
}

只需要调用

MySqListMovingAverageWindowFilter( &L , data)

这个函数,就可以实现低通滤波,可以通过改变 MAXSIZE 的值,来改变滑动窗窗口大小。调用这个函数,直到返回的数不为0,则表示数组已经填充完毕,开始滑动窗滤波。


http://www.niftyadmin.cn/n/1709427.html

相关文章

Jquery ajax参数设置

参数名 类型 描述 url String (默认: 当前页地址) 发送请求的地址。 type String (默认: "GET") 请求方式 ("POST" 或 "GET")&#xff0c; 默认为 "GET"。注意&#xff1a;其它 HTTP 请求方法&#xff0c;如 PUT 和 Delete 也可以使用…

Realview MDK中启动代码的配置详解

转自&#xff1a;http://www.realview.com.cn/bbs/dispbbs.asp?boardID2&ID1532&page38Realview MDK中启动代码的配置详解 Embest 徐良平 Realview MDK不仅提供了默认的启动代码&#xff0c;而且这些启动代码可以通过图形化界面配置。启动代码的图形化配置界面非常类似…

.NET 中 模糊查询拼接SQL时SqlParameter 如何赋值问题

SqlParameter传递参数时&#xff0c;一般情况下&#xff0c;不会受到T-SQL语法关键字的影响。所以安全性比较好&#xff0c;而且不用开发人员额外过滤SQL语法关键字等。在拼接SQL时&#xff0c;如果是&#xff1d;&#xff0c;比较方便&#xff0c;直接WHERE OperateID key&…

poi tl 判断空值_poi读取数据怎么做非空判断和读取指定行

public ResponseResult uploading(MultipartFile file1) throws IOException {String filename file1.getOriginalFilename();// 1.流读取文件FileInputStream stream new FileInputStream("C:\\Users\\admin\\Desktop\\sss\\" filename);// 2.通过poi解析流 得到…

Linq体验(一)

用户表Userss 一&#xff09;where 语句 SelfDataDataContext cc new SelfDataDataContext();protected void Button1_Click(object sender, EventArgs e){ //查询女性好汉var result from p in cc.userss where p.sex.Equals("女") select p;GridView1.Dat…

未能建立连接,原因:SQL Server 2005[SQL-DMO]必须使用管理工具才能连接到此服务器,怎么办?...

SQL Server Express 2005&#xff08;以下简称 SQLExpress&#xff09; 是由微软公司开发的 SQL Server 2005&#xff08;以下简称 SQL2005&#xff09;的缩减版&#xff0c;这个版本是免费的&#xff0c;它继承了 SQL Server 2005 的多数功能与特性&#xff0c;如&#xff1a;…

C# 使用 Environment.GetCommandLineArgs 方法 制作*.exe和参数 供其他程序调用

Environment..::.GetCommandLineArgs 方法 &#xff1a; 返回包含当前进程的命令行参数的字符串数组。 语法&#xff1a; public static string[] GetCommandLineArgs() 返回值类型&#xff1a;System.String[]字符串数组&#xff0c;其中的每个元素都包含一个命令行参数。第一…

python字符串中最长的连续升序子串_求最长回文子串算法——马拉车算法

Manachers Algorithm&#xff0c;中文名叫马拉车算法&#xff0c;是一位名叫Manacher的人在1975年提出的一种算法&#xff0c;解决的问题是求最长回文子串&#xff0c;神奇之处在于将算法的时间复杂度精进到了O(N)&#xff0c;下面我们来详细介绍下这个算法的思路。01 算法由来…