前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据结构算法整理-07-排序算法

数据结构算法整理-07-排序算法

作者头像
devi
发布2021-08-18 15:41:23
2280
发布2021-08-18 15:41:23
举报
文章被收录于专栏:搬砖记录

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ARRAYSIZE 1000  /*数组长度  */

1. 直接插入排序算法 (重点)

跟斗地主摸牌然后插入手牌差不多,每次将待排序的记录(摸的牌)插入到已经排好序的文件当中(有序的手牌)

1.1 带哨位

代码语言:javascript
复制
//直接插入排序算法 
void  insertSort (int  array[ ], int length)
{
	int i, j;
	for(i=2;i<=n;i++) //array[0]作为哨位,而array[1]作为第一张手牌无需比较
	{
		array[0]=array[i];//哨兵上岗,是array[i]的副本
		j=i-1;  //待比较的值
		while(array[0]<array[j]){ //从右至左在有序区array[1..i-1]中查找array[i]的插入位置
			array[j+1]=array[j];  //逐一后移
			j--;
		}
		array[j+1]=array[0];  //将array[i]插入
		
	}
}

1.2 不带哨位

代码语言:javascript
复制
void  insertSort (int  array[ ], int length){
	for(int i=1;i<length;i++){
		int temp = array[i];
		int j;
		for(j=i-1;j>=0;j++){
			if(array[j]>temp)
				array[j+1]=array[j];
			else
				break;
		}
		array[j+1]=temp;
	}
}

哨兵的作用: 1.保存array[i]的副本,防止记录后移丢失array[i] 2.用于监视j是否越界(省略了循环判定条件j≥1))

2. 希尔排序算法 (重点)

同样是摸牌排序,但是此时是n个人摸牌(n=增量),每个人给自己的手牌排序(直接插入排序),最终将n个人的牌放到一起

代码语言:javascript
复制
//希尔排序算法 
void  shellSort (int  r[ ], int n)
{ 	int i,j,d;
	for (d=n/2; d>=1; d=d/2) 
	{
		for (i=d+1; i<=n; i++)  //将r[i]插入到所属的子序列中
		{
     		r[0]=r[i];                     //暂存待插入记录 
     		j=i-d;                   //j指向所属子序列的最后一个记录
     		while (j>0 && r[0]<r[j])
     		{ 
          		r[j+d]=r[j];       //记录后移d个位置
          		j=j-d;            //比较同一子序列的前一个记录
      		}
      		r[j+d]=r[0];       		
		}
		//displayArray(r,n);   //调试用,便于查看中间结果 
	}
}

3. 冒泡排序算法 (基本交换排序)(重点)

从“最下面”的一个泡泡开始,如果它比上一个泡泡大(小),则让它上浮(交换顺序)

代码语言:javascript
复制
//冒泡排序算法 
void bubbleSort(int r[ ], int n)
{	
	for(int i=0;i<n-1;i++)
		for(int j=0;j<n-i-1;j++){
			if(r[j]>r[j+1]){
				int temp=r[j];
				r[j]=r[j+1];
				r[j+1]=temp;
			}
		}
 }

4. 快速排序算法 (重点)

原理:

  1. 任意选择一个基准点
  2. 从右向左遍历序列,若存在比基准点小的,则将其与基准点交换
  3. 从左向右遍历序列,若存在比基准点大的,则将其与基准点交换
  4. 重复2-3操作
代码语言:javascript
复制
void quickSort(int array[],int low,int high)
{
	int i,j;
	int key;
	if(low>high)
		return;
	i=low;
	j=high;
	key=array[low];   //将左侧的数作为基准点
	
	//先对右侧的进行遍历
	while(i!=j){
		while(array[j]>=key&&i<j){
			j--;
		}
		while(array[i]<=key&&i<j){
			i++;
		}
		if(i<j){  //交换i、j对应的值
			int temp;
			temp=array[i];
			array[i]=array[j];
			array[j]=temp;
		}
	
	}
	//当i=j跳出循环
	//重合点作为新的基准值
	array[low] = array[i];  //新的基准值放到low位置
	array[i] = key;  //旧的基准值放在重合点
	
	//以重合点为界,对左右划分进行递归快排
	quickSort(array,low,i-1);  
	quickSort(array,i+1,high);
}

//初次调用的时候,low=1,high=array.length

5. 选择排序

从整个序列中找到最小(大)的一个,让它与当前位置的元素交换(也是待排序序列–>有序序列) 不断重复上述过程

代码语言:javascript
复制
//选择排序 
void selectSort(int r[],int n)
{
	int i,j,d=0;
	for(i=1;i<n;i++)
	{
		d = i;
		for(j=i+1;j<=n;j++)
		{
			if(r[j]<r[d]) d=j;
		}
		if(d!=i) {r[0]=r[i];r[i]=r[d];r[d]=r[0];}//swap(&k[i],&k[d]);
		//displayArray(r,n);   //调试用,便于查看中间结果 
	}
}

6. 堆排序算法

大根堆:根节点比左右子节点大 小根堆:根节点比左右子节点小

小根堆筛选法堆调整: 从树的最右下方的子树开始,将该子树调整为小根堆(根节点比左右子节点小) 从下往上、从右往左重复操作直至到达根节点 从上往下检查小根堆

6.1 堆调整

代码语言:javascript
复制
void shift ( int r[ ], int k, int m )
{	int i,j;
	int temp;
	//要筛选结点的编号为k,堆中最后一个结点的编号为m 
    i=k;  j=2*i;  temp=r[i];  //将筛选记录暂存
    while (j<=m )           //筛选还没有进行到叶子
    {
        if (j<m && r[j]<r[j+1]) j++;  //左右孩子中取较大者
        if (temp >r[j]) break; 
        else {
             r[i]=r[j];   i=j;   j=2*i;
        }
     }
     r[i]=temp;   //将筛选记录移到正确位置
}

6.2 堆排序

代码语言:javascript
复制
void  heapSort ( int  r[], int n)
{
    int i,j;
	for (i=n/2; i>=1; i--)      //初建堆
       shift(r, i, n) ;  
	     
 	//displayArray(r,n);  
 	
    for (i=1; i<n; i++ )
    {  j = n-i+1;
       r[0]=r[1];r[1]=r[j];r[j]=r[0];;        //移走堆顶
       shift(r, 1, n-i);               //重建堆
       //displayArray(r,n);   //调试用,便于查看中间结果 
    }
}

7. 归并

将n个序列单独拿出来排序,最终合并 比如二路归并 1 3 5 4 9 7 (1 3) (4 5) (7 9)

7.1 归并相邻两个子序列

代码语言:javascript
复制
//归并相邻两个子序列 
void Merge (int r[ ], int r1[ ], int s, int m, int t )
{	int i,j,k;
    i=s;   j=m+1;   k=s;
    while (i<=m && j<=t)
    {   
        if (r[i]<=r[j])  r1[k++]=r[i++];
        else  r1[k++]=r[j++]; 
     }
     if (i<=m)  while (i<=m)              //收尾处理
                           r1[k++]=r[i++];    //前一个子序列
     else  while (j<=t)
                  r1[k++]=r[j++];             //后一个子序列
} 

7.2 一趟二路归并

代码语言:javascript
复制
//一趟二路归并 
void  MergePass (int  r[ ], int  r1[ ], int  n, int  h)
{
     int i=1,k=1;
     while (i <= n-2*h+1)                //情况1
     {
           Merge (r, r1, i, i+h-1,i+2*h-1);
           i+=2*h;
      }
      if (i< n-h+1) Merge (r, r1, i,i+h-1, n);   //情况2
      else for (k=i; k<=n; k++)    //情况3
                 r1[k]=r[k];
}

7.3 二路归并

代码语言:javascript
复制
//二路归并排序算法 
void  MergeSort (int r[ ], int r1[ ], int n )
{	int h;
    h=1;
    while (h<n)
    {
         MergePass (r, r1, n, h);
         h=2*h;
         //displayArray(r1,n);  //调试用,便于查看中间结果
         MergePass (r1, r, n, h);
         h=2*h;
         //displayArray(r,n); //调试用,便于查看中间结果
    }
} 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/12/22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 直接插入排序算法 (重点)
    • 1.1 带哨位
      • 1.2 不带哨位
      • 2. 希尔排序算法 (重点)
      • 3. 冒泡排序算法 (基本交换排序)(重点)
      • 4. 快速排序算法 (重点)
      • 5. 选择排序
      • 6. 堆排序算法
        • 6.1 堆调整
          • 6.2 堆排序
          • 7. 归并
            • 7.1 归并相邻两个子序列
              • 7.2 一趟二路归并
                • 7.3 二路归并
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档