算法-排序
2016-12-14 15:53
274 查看
线性表-排序
定义结构体
直接插入排序
简单交换排序
简单选择排序
1.定义
基于线性表的排序排序是计算机数据处理的基本操作和重要技术,能有效提高一个数据处理系统的运行效率.
排序设计要的几个要素
1.排序对象.待排序对象,通常是一个线性表
2.排序标准.定序的依据,由数据元素中一个或者一组数据项充当,这些数据项称为排序关键字,简称关键字
3.排序方向.按照关键字递增还是递减排序.
4.排序操作.排序方法和技术,即排序算法或可执行的排序程序.
5.排序结果.已排好序的序列,或称结果序列.
2.结构体
在SequenStruct.c#include <stdio.h> #define M 100 typedef struct { int data[M]; int n; }SEQUENLIST;
3.直接插入排序
3.1基本思想
直接插入排序的基本思想是,把待排序序列一分为二,前部分为”已排序子序列”,后部分为”待排序子序列”.排序过程即使把”待排序子序列”中的元素一个一个地插入到”已排序子序列”中正确位置上并保证有序,直到”待排序子序列”为空为止.3.2算法思路
设顺序表S,存储一维数组,长度为n.i,j为整数变量.i标记已排序子序列和待排序子序列的分界点,指向待排序子序列的第1个结点,也就是控制排序是否结束的标记.j用于寻找插入位置时指示已排序子序列范围内的位置,初值为i-1,并且寻找过程中不断减1.在第一个数组元素前增设一个数组元素S[0],称为”哨兵”结点,用于存储当前待插入的结点,以空出该结点原来的位置.因为查找插入位置是从已排序子序列尾部向前进行,所以”哨兵”结点起监视查找终止作用.由于向已排序子序列插入结点时要后移一个结点位置,所以该方法是一边查找一边移动,这样不会造成结点丢失.3.3算法实现
在Algorithm.h写出方法声明/* 直接排序算法 */ SEQUENLIST istSortMethod(SEQUENLIST A);
在Algorithm.c中实现此方法
#include "Algorithm.h" /* 直接排序算法 */ SEQUENLIST istSortMethod(SEQUENLIST S){ //1.顺序表中第一个数据为"哨兵",不列入排序的对象 int i,j; //2.如果顺序表中排序的数据就一个元素,算法结束 if(S.n<=2){ return S; } //3.将队列分为"已排序子序列"和"未排序子序列" //S.data[0]为哨兵,用于存在当前待插入的结点 //已排序子序列:S.data[1], //待排序子序列:S.data[2]......S.data[S.n]; for(i=2;i<S.n;i++){ //3.1将要排序的数据赋给哨兵 S.data[0]=S.data[i]; //3.2哨兵在已排序子序列查找位置 for(j=i-1;j>0;j--){ //如果哨兵小于已排序子序列元素(从后往前查找),那么把当前位置往后移动一位 if(S.data[0]<=S.data[j]){ S.data[j+1]=S.data[j]; }else{ //如果哨兵和当前比较的大于等于,且终止循环 break; } } //3.3把哨兵放在当前位置的后面,这句话要放在循环的后面,为了防止此时的哨兵是已排序子序列最小的,那么循环直接结束,直接放在了S.data[1]的位置, S.data[j+1]=S.data[0]; } //4.将哨兵置为-1 S.data[0]=-1; printf("直接排序成功succcess!\n"); return S; }
在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断
#include "Algorithm.h" int main(int argc, const char * argv[]) { //直接排序算法 printf("直接排序算法\n"); //数据的第一个数据-1,作为哨兵 SEQUENLIST A={{-1,4,6,1,5,9,7,4,6,8,3},11}; printSequenList(A); A=istSortMethod(A); printSequenList(A); }
打印结果:
直接排序算法 sequen={{-1,4,6,1,5,9,7,4,6,8,3},11} 直接排序成功succcess! sequen={{-1,1,3,4,4,5,6,6,7,8,9},11} Program ended with exit code: 0
注意:
在创建顺序表的时候,把数据的第一个位置留了出来,作为哨兵,其实要排序的数据是从第二个位置到第n个位置
4.简单交换排序
4.1基本思想
简单交换排序又称冒泡排序.比如:进行从小到大的排序.基本思想:就是把待排序序列分成”已排序子序列”和”未排序子序列”初始时,已排序序列为空.先从待排序子序列(n)中,查找最小的结点然后放到已排序的序列中,然后在从待排序的(n-1)个结点中再次查找出最小的结点,然后放到已排序子序列的后面,这样一直循环,直到待排序序列为最后一个结点,已排序序列的长度为n-1.那么就直接把待排序的序列剩下的最后一个结点就是最大的,不需要比较,直接放到已排序子序列后面.把关键字较小的节点看成”气泡”,每次较小的气泡浮出了水泡,不断的向上”冒”,所以简称”冒泡”排序.4.2算法思路
设顺序表S,存储为一维数组,长度为n,要求用简单交换排序方法对其进行排序.排序的核心就是结点扫描.扫描就结点序列的循环过程.在扫描中,”最小”结点渐渐漂浮到它的正当位置.为此,用整数变量i来标记扫描完成后最小结点位置;同时也把扫描范围控制到i和n之间,i初始值为1,即表示第1趟扫描,也表示现在要漂浮出的最小结点必须存储在1号结点位置.i的终值是n-1.说明最多要作n-1次扫描,是一个循环.为控制扫描过程,还要设置一个变量j,j从n想i逐1推进,控制扫描过程的结束,对每一次扫描,j的初值总为n.在排序过程中不断的进行排序,到最后也许一些顺序已经排序好,不会再发生结点的交换,就没有必要再次进行扫描查找,所以增加一个变量k=1;每次进行排序,也判断一下,如果k=1,在进行这一轮的扫描, 此时设置 k=0,在查找最小结点时候,如果发生了结点的交换k=1.如果在进行新一款的扫描查找的时候,如果发现k=0,那么就表示上一轮的扫描没有发生结点的交换,后面的顺序已经是正确的,那么没有比较进行此轮的循环遍历.
4.3算法实现
在Algorithm.h写出方法声明/* 冒泡排序 */ SEQUENLIST sisSortMethod(SEQUENLIST A);
在Algorithm.c中实现此方法
#include "Algorithm.h" SEQUENLIST sisSortMethod(SEQUENLIST S){ //1.判断顺序表的结点数据的数量 if(S.n<2){ return S; } int count=0; int k=1; //2.查找扫描的次数,即:n-1次,并且k==1,表示前一次发生过结点交换 for(int i=0;i<S.n-1 && k==1 ;i++){ k=0; count++; //3.从待排序自序列,从后往前逐1扫描,直到i的位置 for(int j=S.n-1;j>0;j--){ count++; //3.1比较相邻结点的大小 if(S.data[j]<S.data[j-1]){ //3.2后面结点小于相邻的前一个结点数据,那么就交换 int temp=S.data[j-1]; S.data[j-1]=S.data[j]; S.data[j]=temp; //3.3 设置k=1,表示进行了结点的交换 k=1; } } } printf("冒泡排序成功success! 排序次数:count=%d\n",count); return S; }
在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断
#include "Algorithm.h" int main(int argc, const char * argv[]) { //冒泡排序 printf("冒泡排序\n"); SEQUENLIST S={{88,9,10,7,55,54,98,97,100,99},10}; printSequenList(S); S=sisSortMethod(S); printSequenList(S); }
打印结果:
冒泡排序 sequen={{88,9,10,7,55,54,98,97,100,99},10} 冒泡排序成功success! 排序次数:count=60 sequen={{7,9,10,54,55,88,97,98,99,100},10}
5.简单选择排序
5.1基本思想
简单选择排序的思想是基于简单交换排序.但简单排序有一个很大的缺点,每一次比较都有可能发生两点交换.而简单选择排序在一趟扫描结束后最多只有一次结点交换.显然时间效率比简单交换排序好多了.设待定排序序列为{R1,R2,….Rn},要求对其进行递增方向的排序.简单选择排序的基本思想是,先对整个待排序序列进行扫描,先找到关键字最小的结点,并与第1个结点交换.称为第1趟扫描.把待排序序列分成了”已排序子序列”和”待排序子序列”两部分.初始时,已排序子序列为空.第二趟扫描对除了第一个结点以外的结点进行扫描,找到次小结点与第2个结点进行交换,已排序子序列增加了一个结点,待排序子序列减少一个结点.如此反复,直到最后一个结点到位,所有结点都进入已排序子序列中,待排序子序列为空.扫描开始时总是把待排序序列的第1个结点假设为最小结点,并记录它的位置号.在扫描过程中,若遇到比他更小的结点时就更换记录新位置号,使扫描完成后记录的位置号是最小结点的位置号.
5.2算法思路
设顺序表S,存储为一维数组,长度为n,要就用简单选择排序方法对其进行排序.这个排序过程的n-1扫描是一个循环,控制每一个”最小”结点的选择.每一次扫描也是一个循环,主要操作是比较,为此,设置整数i,j,k.i控制扫描的循环,初值为1,j控制扫描中的比较,初值值i+1,.k记录最小结点位置号,初值为i.5.3算法实现
在Algorithm.h写出方法声明/* 简单选择排序 */ SEQUENLIST sssSortMethod(SEQUENLIST S);
在Algorithm.c中实现此方法
#include "Algorithm.h" SEQUENLIST sssSortMethod(SEQUENLIST S){ //1.判断S数据长度 if(S.n<2){ return S; } int k; //2.开始最外层循环 for(int i=0;i<S.n;i++){ //3.使用k记录当前的位置号 k=i; //4.开始查找数值最小的位置号 for(int j=i+1;j<S.n;j++){ //5.如果当前的位置的数据小于k所在的位置号 if(S.data[j]<S.data[k]){ //6.则把k作为新的位置号 k=j; } } //7.判断k所在的位置号和i所在的位置号是否一样,如果不一样,表示找到了比S.data[i]位置更小的数据 //交换两个节点数据 if(k!=i){ int temp=S.data[i]; S.data[i]=S.data[k]; S.data[k]=temp; } } printf("简单选择排序成功sucess!\n"); return S; }
在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断
#include "Algorithm.h" int main(int argc, const char * argv[]) { //简单选择排序 printf("简单选择排序\n"); SEQUENLIST B={{88,9,10,7,55,54,98,97,100,99},10}; printSequenList(B); B=sssSortMethod(B); printSequenList(B); printf("\n"); }
打印结果:
简单选择排序 sequen={{88,9,10,7,55,54,98,97,100,99},10} 简单选择排序成功sucess! sequen={{7,9,10,54,55,88,97,98,99,100},10}
这里对简单基本排序算法的一些介绍和实现,直接插入排序,简单插入排序,简单交换排序.三个方法中简单交换排序效率比较高.
源码下载
线性表-排序
定义
结构体
直接插入排序
1基本思想
2算法思路
3算法实现
简单交换排序
1基本思想
2算法思路
3算法实现
简单选择排序
1基本思想
2算法思路
3算法实现
相关文章推荐
- 白话经典算法系列之六 快速排序 快速搞定
- 算法3:最常用的排序——快速排序
- Java(.NET)经典排序算法之快速排序
- [算法] 排序方法复杂度、稳定性汇总
- 算法学习——不交换的选择排序
- 算法分析-数组6种排序(少桶排序)
- 算法小结-冒泡、选择排序、直接插入排序
- 【算法-排序之一】冒泡排序
- 算法导论——2.1-2选择排序
- 白话经典算法系列之五 归并排序的实现
- 基础算法(排序)
- 算法---选择排序
- 关于利用STL中的sort算法对向量等容器进行排序的问题
- 四.c++中的算法--排序及相关操作---根据某个元素排序
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
- 堆排序原理及算法实现(最大堆)
- 第十五周项目1 验证算法(2)插入排序之希尔排序
- 算法---快速排序
- javascript 排序(Sorting)算法与说明
- 用C++的基本算法实现十个数排序