数据结构和算法系列7 七大排序之直接插入排序和希尔排序

这一篇要总结的是插入排序中的直接插入排序和希尔排序,主要分以下几点进行总结。

1,直接插入排序及算法实现

2,希尔排序及算法实现

3,直接插入排序PK希尔排序

1,直接插入排序及算法实现

什么是直接插入排序呢?直接插入排序的基本思想是:每次从无序表中取出第一条记录插入到已经排好序的有序表中,从而得到一个新的,记录数增1的有序表。

直接插入排序的图解说明。

下面是直接插入排序的算法实现代码。

C#版:

namespace InsertSort.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int> { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
            Console.WriteLine("********************直接插入排序********************");
            Console.WriteLine("排序前:");
            Display(list);

            Console.WriteLine("排序后:");
            InsertSort(list);
            Display(list);

            Console.ReadKey();
        }

        /// <summary>
        /// 直接插入排序算法
        /// </summary>
        /// <param name="list"></param>
        public static void InsertSort(List<int> list)
        {
            //从无序序列中取出第一条记录(注意无序区是从第二个元素开始的,第一个元素作为哨兵元素)
            for (int i = 1; i < list.Count; i++)
            {
                int temp = list[i];

                int j;

                //遍历有序序列
                //如果有序序列中最末元素比临时元素(无序序列第一个元素)大,则将有序序列中比临时元素大的元素依次后移
                for (j = i - 1; j >= 0 && list[j]>temp; j--)
                {
                    list[j + 1] = list[j];
                }

                //将临时元素插入到腾出的位置中
                list[j + 1] = temp;
            }
        }

        private static void Display(List<int> list)
        {
            Console.WriteLine("
**********展示结果**********
");

            if (list != null && list.Count > 0)
            {
                foreach (var item in list)
                {
                    Console.Write("{0} ", item);
                }
            }

            Console.WriteLine("
**********展示完毕**********
");
        }
    }
}

程序输出结果:

ds27

 

C语言版:

/*包含头文件*/
#include "stdio.h"
#include "stdlib.h"   
#include "io.h"
#include "math.h" 
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100

typedef int Status; 
typedef struct
{
    int data[MAXSIZE];
    int length;    
}SeqList;

/*直接插入排序*/
void InsertSort(SeqList *seqList)
{
    int i,j;

    /*从无序序列中取出第一条记录(注意无序区是从第二个元素开始的,第一个元素作为哨兵元素)*/
    for (i=1;i<seqList->length;i++)
    {
        int temp=seqList->data[i];

        /*遍历有序序列
        如果有序序列中最末元素比临时元素(无序序列第一个元素)大,则将有序序列中比临时元素大的元素依次后移
        */
        for (j=i-1;j>=0&&seqList->data[j]>temp;j--)
        {
            seqList->data[j+1]=seqList->data[j];
        }

        /*将临时元素插入到腾出的位置中*/
        seqList->data[j+1]=temp;
    }

}

/*打印结果*/
void Display(SeqList *seqList)
{
    int i;
    printf("
**********展示结果**********
");

    for (i=0;i<seqList->length;i++)
    {
        printf("%d ",seqList->data[i]);
    }

    printf("
**********展示完毕**********
");
}

#define N 9
void main()
{
    int i,j;
    SeqList seqList;

    //定义数组和初始化SeqList
    int d[N]={50,10,90,30,70,40,80,60,20};

    for (i=0;i<N;i++)
    {
        seqList.data[i]=d[i];
    }
    seqList.length=N;

    printf("***************直接插入排序***************
");
    printf("排序前:");
    Display(&seqList);

    InsertSort(&seqList);
    printf("
排序后:");
    Display(&seqList);

    getchar();
}

程序输出结果同上

2,希尔排序及算法实现

希尔排序是直接插入排序的改进版本,简单来说就是一种“缩小增量排序”的思想。

C#版实现代码:

namespace ShellSort.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int> { 50, 10, 90, 30, 70, 40, 80, 60, 20 };
            Console.WriteLine("********************希尔排序********************");
            Console.WriteLine("排序前:");
            Display(list);

            Console.WriteLine("排序后:");
            ShellSort(list);
            Display(list);

            Console.ReadKey();
        }

        /// <summary>
        /// 希尔排序算法
        /// </summary>
        /// <param name="list"></param>
        public static void ShellSort(List<int> list)
        {
            //取增量
            int step = list.Count / 2;

            while (step >= 1)
            {
                //无序序列
                for (int i = step; i < list.Count; i++)
                {
                    int temp = list[i];
                    int j;

                    //有序序列
                    for (j = i - step; j >= 0 && list[j] > temp; j = j - step)
                    {
                        list[j + step] = list[j];
                    }
                    list[j + step] = temp;
                }

                //缩小增量
                step = step / 2;
            }
        }

        private static void Display(List<int> list)
        {
            Console.WriteLine("
**********展示结果**********
");

            if (list != null && list.Count > 0)
            {
                foreach (var item in list)
                {
                    Console.Write("{0} ", item);
                }
            }

            Console.WriteLine("
**********展示完毕**********
");
        }
    }
}

程序输出结果如图:

ds28

 

C语言版:

/*包含头文件*/
#include "stdio.h"
#include "stdlib.h"   
#include "io.h"
#include "math.h" 
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100

typedef int Status; 
typedef struct
{
    int data[MAXSIZE];
    int length;    
}SeqList;

/*希尔排序算法*/
void ShellSort(SeqList *seqList)
{
    int i,j;
    /*取增量*/
    int step=seqList->length/2;

    while (step>=1)
    {
        /*无序序列*/
        for (i=step;i<seqList->length;i++)
        {
            int temp=seqList->data[i];

            /*有序序列*/
            for (j=i-step;j>=0&&seqList->data[j]>temp;j=j-step)
            {
                /*交换位置*/
                seqList->data[j+step]=seqList->data[j];
            }
            seqList->data[j+step]=temp;
        }

        /*缩小增量*/
        step=step/2;
    }
}

/*打印结果*/
void Display(SeqList *seqList)
{
    int i;
    printf("
**********展示结果**********
");

    for (i=0;i<seqList->length;i++)
    {
        printf("%d ",seqList->data[i]);
    }

    printf("
**********展示完毕**********
");
}

#define N 9
void main()
{
    int i,j;
    SeqList seqList;

    //定义数组和初始化SeqList
    int d[N]={50,10,90,30,70,40,80,60,20};

    for (i=0;i<N;i++)
    {
        seqList.data[i]=d[i];
    }
    seqList.length=N;

    printf("***************希尔排序***************
");
    printf("排序前:");
    Display(&seqList);

    ShellSort(&seqList);
    printf("
排序后:");
    Display(&seqList);

    getchar();
}

思路基本与C#版一样,输出结果也同上。

3,直接插入排序PK希尔排序

既然说希尔排序是直接插入排序的改进版,我们就来通过一段测试程序来看看希尔排序是否真的就比直接插入排序快?

测试代码:

static void Main(string[] args)
        {
            //共进行三次比较
            for (int i = 1; i <= 3; i++)
            {
                //初始化List
                List<int> list = new List<int>();
                for (int j = 0; j < 1000; j++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(10000, 1000000));
                }

                //复制一份供希尔排序调用
                List<int> list2 = new List<int>();
                list2.AddRange(list);

                //直接插入排序耗费时间
                Console.WriteLine("" + i + "次比较:");
                Stopwatch watch = new Stopwatch();
                watch.Start();
                InsertSort.CSharp.Program.InsertSort(list);
                watch.Stop();
                Console.WriteLine("
直接插入排序耗费时间:" + watch.ElapsedMilliseconds);
                Console.WriteLine("输出前十个数:" + String.Join(",", list.Take(10).ToList()));

                //希尔排序耗费时间
                watch.Start();
                ShellSort(list2);
                watch.Stop();
                Console.WriteLine("
希尔排序耗费时间:" + watch.ElapsedMilliseconds);
                Console.WriteLine("输出前十个数:" + String.Join(",", list2.Take(10).ToList()));
            }

            Console.ReadKey();
        }

程序输出结果如下:

ds29

我的电脑测出来的结果反而是希尔排序要比直接插入排序要慢一点,不知道是为什么?

原文地址:https://www.cnblogs.com/mcgrady/p/3256117.html