直接插入排序

合集下载

直接插入排序 快速排序 大根堆排序 归并排序

直接插入排序 快速排序 大根堆排序 归并排序

#include<stdio.h>#include<malloc.h>#include<stdlib.h>#include<time.h>#define MAXSIZE 100/***************定义和初始化顺序表************************/ typedef int DataType;typedef struct node {DataType data[MAXSIZE];int length;}SeqList,*PseqList;//定义一个顺序表。

PseqList Init_SeqList(void){PseqList PL;PL=(PseqList)malloc(sizeof(SeqList));if(PL)PL->length=0;return(PL);}//顺序表的初始化./*********************直接插入排序**********************/ void StraightInsertSort(SeqList *s){int i,j;for(i=2;i<s->length;i++){s->data[0]=s->data[i];for(j=i-1;s->data[0]<s->data[j];j--){s->data[j+1]=s->data[j];}s->data[j+1]=s->data[0];}}/*******************快速排序************************/int QuickSort1(SeqList *s,int low,int high){s->data[0]=s->data[low];while(low<high){while(low<high&&s->data[high]>=s->data[0])high--;s->data[low]=s->data[high];while(low<high&&s->data[low]<=s->data[0])low++;s->data[high]=s->data[low];}s->data[low]=s->data[0];return low;}void QuickSort(PseqList s,int low,int high){int m;if(low<high){m=QuickSort1(s,low,high);QuickSort(s,low,m-1);QuickSort(s,m+1,high);}}/******************大根堆排序************************/ void HeapAdjust(SeqList *s,int n,int m){int i,j;s->data[0]=s->data[n];i=n;for(j=2*i;j<=m;j=j*2){if(j<m&&s->data[j]<s->data[j+1])j++;if(s->data[0]>s->data[j]) break;s->data[i]=s->data[j];i=j;}s->data[i]=s->data[0];}void HeapSort(SeqList *s){int i;for(i=s->length/2;i>0;i--)HeapAdjust(s,i,s->length-1);for(i=s->length-1;i>1;i--){s->data[0]=s->data[1];s->data[1]=s->data[i];s->data[i]=s->data[0];HeapAdjust(s,1,i-1);}}/*****************归并排序************************/ void Merge(DataType r[],DataType rf[],int u,int v,int t){int i,j,k;for(i=u,j=v+1,k=u;i<=v&&j<=t;k++){if(r[i]<=r[j]){rf[k]=r[i];i++;}else{rf[k]=r[j];j++;}}while(i<=v) rf[k++]=r[i++];while(j<=t) rf[k++]=r[j++];}void MSort(DataType p[],DataType p1[],int n,int t){int m;DataType p2[MAXSIZE+1];if(n==t)p1[n]=p[n];else{m=(n+t)/2;MSort(p,p2,n,m);MSort(p,p2,m+1,t);Merge(p2,p1,n,m,t);}}void MergeSort(PseqList s){MSort(s->data,s->data,1,s->length-1);}/********************主函数*************************/ void main(){PseqList p;int i,n=0;srand((unsigned)time(NULL));p=Init_SeqList();for(i=1;i<=20;i++){p->data[i]=rand()%20+1;}p->length=i;printf("输出原序列:\n");for(i=1;i<p->length;i++) printf("%3d",p->data[i]);while(n==0||n==1||n==2||n==3||n==4){printf("\n请选择:1.直接插入排序;2.快速排序;3.大根堆排序;4.归并排序;其它退出\n");n=0;scanf("%d",&n);switch(n){case 1:StraightInsertSort(p);printf("输出直接插入排序后序列:\n");break;case 2:QuickSort(p,1,p->length-1);printf("输出快速排序序列:\n");break;case 3:HeapSort(p);printf("输出大根堆排序序列:\n");break;case 4:MergeSort(p);printf("输出归并排序序列:\n");break;default:printf("******error!*******\n");return;}for(i=1;i<p->length;i++) printf("%3d",p->data[i]);printf("\n");}}。

源代码--数据结构与算法(Python版)chap10 排序

源代码--数据结构与算法(Python版)chap10 排序
20
交换类
(2)快速排序 快速排序采用分而治之(Divide and Conquer)
的策略将问题分解成若干个较小的子问题,采用 相同的方法一一解决后,再将子问题的结果整合 成最终答案。快速排序的每一轮处理其实就是将 这一的基准数定位,直到所有的数都排序完成 为止。
21
快速排序的基本步骤:
1. 选定一个基准值(通常可选第一个元素); 2. 将比基准值小的数值移到基准值左边,形
14
• 交换类
交换类排序的基本思想是:通过交换无序序列 中的记录得到其中关键字最小或最大的记录,并将 其加入到有序子序列中,最终形成有序序列。交换 类排序可分为冒泡排序和快速排序等。
15
交换类
(1)冒泡排序 两两比较待排序记录的关键字,发现两
个记录的次序相反时即进行交换,直到没有 反序的记录为止。因为元素会经由交换慢慢 浮到序列顶端,故称之为冒泡排序。
3. 最后对这个组进行插入排序。步长的选法 一般为 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。
11
【例】给定序列(11,9,84,32,92,26,58,91,35, 27,46,28,75,29,37,12 ),步长设为d1 =5、d2 =3、 d3 =1,希尔排序过程如下:
for i in range(1,len(alist)):
#外循环n-1
for j in range(i,0,-1):
#内循环
if alist[j]<alist[j-1]:
alist[j],alist[j-1]=alist[j-1],alist[j] #交换
li=[59,12,77,64,72,69,46,89,31,9] print('before: ',li) insert_sort(li) print('after: ',li)

c#实现的几种排序方法

c#实现的几种排序方法

c#实现的⼏种排序⽅法1.经典排序算法 – 插⼊排序Insertion sort插⼊排序就是每⼀步都将⼀个待排数据按其⼤⼩插⼊到已经排序的数据中的适当位置,直到全部插⼊完毕。

插⼊排序⽅法分直接插⼊排序和折半插⼊排序两种,这⾥只介绍直接插⼊排序,折半插⼊排序留到“查找”内容中进⾏。

图1演⽰了对4个元素进⾏直接插⼊排序的过程,共需要(a),(b),(c)三次插⼊。

public void Sort(int[] arr){for (int i = 1; i < arr.Length; i++){int t = arr[i];int j = i;while ((j > 0) && (arr[j - 1] > t)){arr[j] = arr[j - 1];//交换顺序--j;}arr[j] = t;}}折半排序算法是对直接插⼊算法的⼀种优化,优化的核⼼是:通过折半查看有序数组中间位置的数值(a)与待插⼊的数值(temp)的⼤⼩,如果a>=temp,则转向折半的左区间继续折半查找;如果a<temp,则转向折半后的右区间继续折半查找。

直到左右下标相同时,此时折半的下标也指向相同的位置,再做最后⼀次循环,最终的结果是:左右下标相差1,并且原来左侧的下标指向⼤于temp的位置,原来右侧的下标指向了⼩于temp的位置,即:array[biggerIndex] < temp < array[smallerIndex]。

//折半排序算法(传递待排数组名,即:数组的地址。

故形参数组的各种操作反应到实参数组上)private static void BinaryInsertionSortFunction(int[] array){try{int smallerIndex = 0; //记录有序数组的起始位置int biggerIndex = 0; //记录有序数组的终⽌位置int midIndex = 0; //记录获取有序数组的中间位置(折半法的关键:折半的位置)int temp; //记录带排的数值for (int i = 1; i < array.Length; i++) //循环向有序数组中插⼊数值(i从1开始,因为操作的是同⼀个数组){temp = array[i]; //记录待插⼊有序数组的数值biggerIndex = i - 1;//当smallerIndex==biggerIndex时,进⼊最后⼀次循环:smallerIndex指向⼤于temp的数组位置,biggerIndex指向⼩于temp的数组位置while (smallerIndex <= biggerIndex){midIndex = (smallerIndex + biggerIndex) / 2; //确定折半的位置if(array[midIndex] >= temp) //折半位置的数值 >= temp{biggerIndex = midIndex - 1; //biggerIndex以midIndex为基础向前移动⼀位}else{smallerIndex = midIndex + 1; //smallerIndex以midIndex为基础向后移动⼀位}}for (int j = i - 1; j >biggerIndex; j--) //将有序数组中⼤于temp的数值分别向后移动⼀位{array[j + 1] = array[j]; //}array[biggerIndex + 1] = temp; //将temp插⼊biggerIndex + 1,因为此时array[biggerIndex]<temp<array[smallerIndex]}}catch (Exception ex){ }}2. //选择排序public static void SelectionSort(int[] num){int min, temp;for (int i = 0; i < num.Length-1; i++){min = i;for (int j =i+1; j < num.Length; j++){if (num[j] < num[min]){min = j;}}temp = num[i];num[i] = num[min];num[min] = temp;}}3. //冒泡排序(Bubble Sort)的基本思想是:将相邻的记录的关键码进⾏⽐较,若前⾯记录的关键码⼤于后⾯记录的关键码,则将它们交换,否则不交换。

c++排序算法

c++排序算法

当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。

快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;1. 插入排序—直接插入排序(Straight Insertion Sort)基本思想:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。

即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,作为临时存储和判断数组边界之用。

直接插入排序示例:如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。

所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

算法的实现:效率:时间复杂度:O(n^2).其他的插入排序有二分插入排序,2-路插入排序。

2. 插入排序—希尔排序(Shell`s Sort)希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。

希尔排序又叫缩小增量排序基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法:1.选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;2.按增量序列个数k,对序列进行k 趟排序;3.每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。

仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序的示例:算法实现:我们简单处理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n为要排序数的个数即:先将要排序的一组记录按某个增量d(n/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。

直接插入排序

直接插入排序

哨兵的作用
哨兵的作用
算法中引进的附加记录R称监视哨或哨兵(Sentinel)。 哨兵有两个作用: ①进入查找(插入位置)循环之前,它保存了R[i]的副本,使不致于因记录后移而丢失R[i]的内容; ②它的主要作用是:在查找循环中"监视"下标变量j是否越界。一旦越界(即j=0),因为R.可以和自己比较, 循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(即省略了循环判定 条件"j>=1")。 注意: ①实际上,一切为简化边界条件而引入的附加结点(元素)均可称为哨兵。 【例】单链表中的头结点实际上是一个哨兵 ②引入哨兵后使得测试查找循环条件的时间大约减少了一半,所以对于记录数较大的文件节约的时间就相当 可观。对于类似于排序这样使用频率非常高的算法,要尽可能地减少其运行时间。所以不能把上述算法中的哨兵 视为雕虫小技,而应该深刻理解并掌握这种技巧。
算法描述
算法描述
Python代码实现 C/C+ve-C实现 JAVA实现 C#实现
谢谢观看
直接插入排序
一种最简单的排序方法
01 简介
03 过程实例
目录
02 哨兵的作用 04 算法描述
基本信息
直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,其基本操作是将一条记录插入到已 排好的有序表中,从而得到一个新的、记录数量增1的有序表。
简介
引言 基本思想
基本思想
每一趟将一个待排序的记录,按其关键字的大小插入到已经排好序的一组记录的适当位置上,直到所有待排 序记录全部插入为止。
待排序记录 R1,R2,…,Rn–1, Rn 第一步:R1 第二步:(R1 ), R2 第三步:(R1, R2), R3 …… 第 j步:(R1,R2,…,Rj–1), Rj …… 第 n步: (R1,R2,…,Rn–1), Rn. 例:j=5

插入排序的基本概念

插入排序的基本概念

插入排序的基本概念插入排序是一种简单直观的排序算法,它通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

插入排序的时间复杂度为O(n^2),但在小规模数据时表现优异,且稳定性较好。

一、基本思想插入排序将待排序数组分为已排好序和未排好序两部分。

每次将未排好序的第一个元素插入到已排好序部分的相应位置,直至全部元素有序。

二、具体实现1. 直接插入排序直接插入排序是最基本的插入排序算法。

它从第二个元素开始遍历待排数组,将当前元素与前面已经排好序的元素依次比较,找到合适位置并插入。

2. 希尔排序希尔排序是直接插入排序的改进版。

它通过设置增量gap来分组进行直接插入排序,每轮对每个组进行一次直接插入排序。

随着增量gap逐渐减小,组数也逐渐减少,当gap=1时即为最后一轮直接插入排序。

三、优化方案1. 二分查找优化在寻找待插入位置时使用二分查找可以提高效率。

二分查找的时间复杂度为O(logn),相比于直接比较可以减少一部分比较次数。

2. 跳跃式插入跳跃式插入是对直接插入排序的优化,它将待插入元素与一定间隔的元素进行比较,从而减少了比较次数。

四、应用场景由于插入排序在小规模数据时表现优异,因此常被用于对小规模数据进行排序。

同时,由于其稳定性较好,也常被用于稳定性要求较高的场景。

五、总结插入排序是一种简单直观的排序算法,通过构建有序序列实现对待排数组的排序。

虽然时间复杂度为O(n^2),但在小规模数据时表现优异,并且稳定性良好。

同时,通过二分查找和跳跃式插入等优化方案可以进一步提高效率。

用Java实现常见的8种内部排序算法

用Java实现常见的8种内部排序算法

⽤Java实现常见的8种内部排序算法⼀、插⼊类排序插⼊类排序就是在⼀个有序的序列中,插⼊⼀个新的关键字。

从⽽达到新的有序序列。

插⼊排序⼀般有直接插⼊排序、折半插⼊排序和希尔排序。

1. 插⼊排序1.1 直接插⼊排序/*** 直接⽐较,将⼤元素向后移来移动数组*/public static void InsertSort(int[] A) {for(int i = 1; i < A.length; i++) {int temp = A[i]; //temp ⽤于存储元素,防⽌后⾯移动数组被前⼀个元素覆盖int j;for(j = i; j > 0 && temp < A[j-1]; j--) { //如果 temp ⽐前⼀个元素⼩,则移动数组A[j] = A[j-1];}A[j] = temp; //如果 temp ⽐前⼀个元素⼤,遍历下⼀个元素}}/*** 这⾥是通过类似于冒泡交换的⽅式来找到插⼊元素的最佳位置。

⽽传统的是直接⽐较,移动数组元素并最后找到合适的位置*/public static void InsertSort2(int[] A) { //A[] 是给定的待排数组for(int i = 0; i < A.length - 1; i++) { //遍历数组for(int j = i + 1; j > 0; j--) { //在有序的序列中插⼊新的关键字if(A[j] < A[j-1]) { //这⾥直接使⽤交换来移动元素int temp = A[j];A[j] = A[j-1];A[j-1] = temp;}}}}/*** 时间复杂度:两个 for 循环 O(n^2)* 空间复杂度:占⽤⼀个数组⼤⼩,属于常量,所以是 O(1)*/1.2 折半插⼊排序/** 从直接插⼊排序的主要流程是:1.遍历数组确定新关键字 2.在有序序列中寻找插⼊关键字的位置* 考虑到数组线性表的特性,采⽤⼆分法可以快速寻找到插⼊关键字的位置,提⾼整体排序时间*/public static void BInsertSort(int[] A) {for(int i = 1; i < A.length; i++) {int temp = A[i];//⼆分法查找int low = 0;int high = i - 1;int mid;while(low <= high) {mid = (high + low)/2;if (A[mid] > temp) {high = mid - 1;} else {low = mid + 1;}}//向后移动插⼊关键字位置后的元素for(int j = i - 1; j >= high + 1; j--) {A[j + 1] = A[j];}//将元素插⼊到寻找到的位置A[high + 1] = temp;}}2. 希尔排序希尔排序⼜称缩⼩增量排序,其本质还是插⼊排序,只不过是将待排序列按某种规则分成⼏个⼦序列,然后如同前⾯的插⼊排序⼀般对这些⼦序列进⾏排序。

24种插入法

24种插入法

24种插入法24种插入法是一种优化排序算法,它的基本思想是将一个列表分为已排序区间和未排序区间,每次从未排序区间取出一个元素,插入到已排序区间的正确位置,使已排序区间保持有序。

在这个过程中,相邻元素的比较和交换次数都很少,所以可以提高排序的效率。

此外,24种插入法还有一些变体,可以根据不同情况选用相应的插入法,达到更好的排序效果。

以下是24种插入法的详细介绍:1. 直接插入排序直接插入排序是最简单的插入法,它将未排序元素插入到已排序区间合适的位置。

时间复杂度为O(n²),空间复杂度为O(1)。

2. 折半插入排序折半插入排序是对直接插入排序的优化,它采用二分查找的方式找到插入位置。

时间复杂度为O(n²),空间复杂度为O(1)。

3. 希尔排序希尔排序是一种针对直接插入排序的改进,它将列表按照一定步长分组,每个子列表采用直接插入排序,随着步长逐渐缩小,最终变为一组,完成排序。

时间复杂度为O(nlogn),空间复杂度为O(1)。

4. 二路插入排序二路插入排序是对直接插入排序的改进,它采用两个指针,在有序区间之前和之后分别插入未排序元素。

时间复杂度为O(n²),空间复杂度为O(1)。

5. 多关键词插入排序多关键词插入排序是针对多关键词排序的优化,它将排序条件拆分为多个关键词,分别进行插入排序。

时间复杂度为O(nlogn),空间复杂度为O(1)。

6. 基数插入排序基数插入排序是对基数排序的优化,它使用插入法对每个桶内的元素进行排序,并合并桶内已排序的元素。

时间复杂度为O(dn),空间复杂度为O(max)。

7. 大小插入排序大小插入排序是对多关键词排序的优化,它根据元素的大小关系建立排序树,对树进行遍历并插入已排序区间。

时间复杂度为O(nlogn),空间复杂度为O(nlogn)。

8. 块插入排序块插入排序是对桶排序的优化,它将待排序元素分为若干块,分别进行插入排序,再将已排序块合并。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include <iostream>
using namespace std;
void insert_sort(int a[],int length)
{
int t;
for(int i=0;i<length;i++)
{
t=a[i]; //将待排序的元素a[i]赋给t
for(int j=i-1;j>=0&&a[j]>t;j--)
{
a[j+1]=a[j]; //把比t大(a[j]>t)的元素,全部后移一个位置 }
a[j+1]=t; //把待排序的t插入到a[j+1].完成插入排序过程。

}
}
int main()
{
int a[5]={12,5,41,36,89};
insert_sort(a,5);
for(int i=0;i<5;i++)
cout<<a[i]<<" ";
return 0;
}
//直接插入排序算法
#include <iostream>
using namespace std;
#define MAXSIZE 20 //定义顺序表的最大长度
//定义顺序表的存储结构
typedef int KeyType; //定义关键字为整数类型typedef struct
{
KeyType key; //关键字项
} RedType; //记录类型
typedef struct
{
RedType r[MAXSIZE+1]; //r[0]用作哨兵单元
int length; //顺序表长度
} SqList; //顺序表类型
//函数原型声明
void InitiSeqList(SqList &L, int n); //初始化顺序表函数
void DisplayNoSort(SqList &L); //输出排序前的顺序表
bool LT(int a, int b); //关键字比较函数
void InsertSort(SqList &L); //插入排序函数
void DisplayInsertSort(SqList &L); //输出排序后的顺序表
//main函数
int main()
{
SqList seqlist;
InitiSeqList(seqlist,MAXSIZE);
DisplayNoSort(seqlist);
InsertSort(seqlist);
DisplayInsertSort(seqlist);
return 0;
}
//初始化顺序表函数,初始化为含n个元素的顺序表
void InitiSeqList(SqList &L, int n)
{
L.length=n; //顺序表长度
for(int i=1; i<=L.length; ++i)
{
L.r[i].key=rand()%90+10; //产生10到100之间的随机数}
}
//输出排序前的顺序表
void DisplayNoSort(SqList &L)
{
cout<<"插入排序前的顺序表:"<<endl;
for(int i=1; i<=L.length; ++i)
{
cout<<L.r[i].key<<" ";
if(i%10==0)
cout<<endl;
}
}
//关键字比较函数
bool LT(int a, int b)
{
return a<b ? true : false;
}
//插入排序函数
void InsertSort(SqList &L)
{
// 对顺序表L作直接插入排序
int i,j;
for (i=2; i<=L.length; ++i)
if (LT(L.r[i].key, L.r[i-1].key)) // "<"时,需将L.r[i]插入有序子表{
L.r[0] = L.r[i]; // 复制为哨兵
for (j=i-1; LT(L.r[0].key, L.r[j].key); --j)
L.r[j+1] = L.r[j]; // 记录后移
L.r[j+1] = L.r[0]; // 插入到正确位置
}
} // InsertSort
//输出经直接插入排序后的顺序表
void DisplayInsertSort(SqList &L)
{
cout<<"插入排序后的顺序表:"<<endl;
for(int i=1; i<=L.length; ++i)
{
cout<<L.r[i].key<<" ";
if(i%10==0)
cout<<endl;
}
}。

相关文档
最新文档