shell排序分享

发布于:2023-01-16 ⋅ 阅读:(349) ⋅ 点赞:(0)

文章目录

  • 一、shell排序
    • 1.shell排序原理
    • 2.代码分析
  • 二、堆排序
    • 1.堆排序原理
    • 2.代码分析
  • 总结

一、shell排序

1.shell排序原理

       shell排序,和Linux的shell程序没有关系;shell排序得名的原因是该排序方法是DL. Shell于1959年基于直接插入排序算法改进提出的,所以命名为shell排序。

      shell排序是基于直接插入排序改进的。

      直接插入排序的思想是:构建一个有序的序列,把新的数字插入到有序序列当中。直接插入排序到问题在于:每次插入都会移动大量空间,造成时间复杂度过大。直接插入排序到时间复杂度为O(n^2)。

      shell排序基于直接插入排序改进:把整个序列分割为多个部分进行插入排序,然后再进行子序列合起来,再进行插入插入排序;这样,减少移动空间次数。直接插入排序的平均时间复杂度为O(n^1.3);最坏的时间复杂度为O(n^2)。

2.代码分析

 int increment=L->last+1;

先将increment的位置放置最后一位

increment=increment/3+1;

此处为选取增量,但如何去选择现在并没有明确的较好的方式去确定

        for(i=increment;i<=L->last;i++)
        {
            if(L->data[i]<L->data[i-increment])
            {   
                //将data[i]的位置空出来,将值暂存在temp中
                int temp=L->data[i];
                for(j=i-increment;j>=0&&L->data[j]>temp;j-=increment)
                {
                    L->data[j+increment]=L->data[j];
                }
                L->data[j+increment]=temp;
            }
        }

进行循环比较,其比较原理是将较小的数放在前面 ,较大的数放在后面,其比较间隔为increment.

其比较方式在下图中做一个简单的解释:

 表中一共有9个元素,则increment为4,那么在比较时间隔四个。

则为 1与5比较;2与6比较;3与7比较;4与8比较;5与9比较;并将较小的值放到前面。第一次循环结果为:

当第二次循环时,increment = 4/3 + 1 =2,

则为:1与3比较;2与4比较;3与5比较;4与6比较;5与7比较;6与8比较;7与9比较,其结果为:

当第三次循环是,increment = 1;则为每一位和他的下一位做比较;

其结果为:

由于采用的是do....while语句,所以即便我们采用的退出条件为 increment >1 但当其=1时,仍要进行一次循环。

另外以上示列并没有完全展现出代码的功能,其中一段代码为:

                for(j=i-increment;j>=0&&L->data[j]>temp;j-=increment)
                {
                    L->data[j+increment]=L->data[j];
                }

 其作用是进行二次比较,例如:

在这组数组当中,当Increment为4的时候,1和5比较后,1号位为 5 ;5号位为6;但当5号为和9号位比较时,5号位变为4,9号位变为5,当后置位交换到前置位时还应和前前置位比较,意为5号位还需要和1号为比较,此时1号位变为4,5号位变为5.以上便是这一段代码的作用。

其完功能代码完整代码为:

#include "sqlist.h"

void shellsort(sqlist_t *L)
{
    int i,j;
    int increment=L->last+1;
    do
    {
        //每轮比较间隔,也叫增量序列
        increment=increment/3+1;
        for(i=increment;i<=L->last;i++)
        {
            if(L->data[i]<L->data[i-increment])
            {   
                //将data[i]的位置空出来,将值暂存在temp中
                int temp=L->data[i];
                for(j=i-increment;j>=0&&L->data[j]>temp;j-=increment)
                {
                    L->data[j+increment]=L->data[j];
                }
                L->data[j+increment]=temp;
            }
        }
    }while(increment>1);
    return ;
}

其获取随机书代码为:

int sqlist_insert(sqlist_t *L, data_t x, int pos)
{
    if(L==NULL)
    {
        printf("list no exist!\n");
        return -1;
    }
    if(is_full(L) || pos < 0 || pos > (L->last+1))
    {
        printf("sqlist can not insert\n");
        return -1;
    }
    for(int i=L->last;i>=pos;i--)
    {
        L->data[i+1]=L->data[i];
    }
    L->data[pos]=x;
    L->last+=1;
    return 0;
}

其头文件为:

#ifndef _SQLIST_H
#define _SQLIST_H

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAXSIZE 100
typedef int data_t;
typedef struct
{
    data_t data[MAXSIZE];
    int last;
}sqlist_t;

int sqlist_insert(sqlist_t *L, data_t x, int pos);

#endid

其主函数为:

#include "sqlist.h"

int main(int argc, char *argv[])
{ 
    srand(time(NULL));
	sqlist_t *L = NULL;
	sqlist_init(&L);
	if(is_full(L) == 1)
		printf("full!\n");
	else
		printf("no full!\n");
    int i=0,ra=0;
	while(i < 10){
		sqlist_insert(L,(ra=rand()%20) , i);
		i++;
	}
	sqlist_show(L);
    shellsort(L);
    sqlist_show(L);
    retuen 0 ;
}

以下为代码运行结果:

no full!
L->data[0]: 9
L->data[1]: 7
L->data[2]: 1
L->data[3]: 14
L->data[4]: 1
L->data[5]: 3
L->data[6]: 2
L->data[7]: 1
L->data[8]: 9
L->data[9]: 14
----------------
L->data[0]: 1
L->data[1]: 1
L->data[2]: 1
L->data[3]: 2
L->data[4]: 3
L->data[5]: 7
L->data[6]: 9
L->data[7]: 9
L->data[8]: 14
L->data[9]: 14
----------------
 


总结

shell排序是将慢速排序提向高速排序的先锋,在整个代码中唯一一个不太容易理解的点在于increment/+1这一个增量当中,但作为一个新手这貌似也不在我的考量范围之内。

以上分享借鉴了《大话数据结构》

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到