亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 邏輯算法 > 正文

算法系列15天速成 第二天 七大經典排序【中】

2024-09-08 23:18:38
字體:
來源:轉載
供稿:網友

首先感謝朋友們對第一篇文章的鼎力支持,感動中....... 

 

今天說的是選擇排序,包括“直接選擇排序”和“堆排序”。

話說上次“冒泡排序”被快排虐了,而且“快排”贏得了內庫的重用,眾兄弟自然眼紅,非要找快排一比高下。

這不今天就來了兩兄弟找快排算賬。

1.直接選擇排序: 

先上圖:

說實話,直接選擇排序最類似于人的本能思想,比如把大小不一的玩具讓三歲小毛孩對大小排個序,

那小孩首先會在這么多玩具中找到最小的放在第一位,然后找到次小的放在第二位,以此類推。。。。。。

,小孩子多聰明啊,這么小就知道了直接選擇排序。羨慕中........

對的,小孩子給我們上了一課,

第一步: 我們拿80作為參照物(base),在80后面找到一個最小數20,然后將80跟20交換。

第二步:  第一位數已經是最小數字了,然后我們推進一步在30后面找一位最小數,發現自己最小,不用交換。

第三步:........

最后我們排序完畢。大功告成。

既然是來挑戰的,那就5局3勝制。

復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace SelectionSort
{
    public class Program
    {
        static void Main(string[] args)
        {
            //5次比較
            for (int i = 1; i <= 5; i++)
            {
                List<int> list = new List<int>();

                //插入2w個隨機數到數組中
                for (int j = 0; j < 20000; j++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 1000000));
                }

                Console.WriteLine("/n第" + i + "次比較:");

                Stopwatch watch = new Stopwatch();

                watch.Start();
                var result = list.OrderBy(single => single).ToList();
                watch.Stop();

                Console.WriteLine("/n快速排序耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + string.Join(",", result.Take(10).ToList()));

                watch.Start();
                result = SelectionSort(list);
                watch.Stop();

                Console.WriteLine("/n直接選擇排序耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + string.Join(",", list.Take(10).ToList()));

            }
        }

        //選擇排序
        static List<int> SelectionSort(List<int> list)
        {
            //要遍歷的次數
            for (int i = 0; i < list.Count - 1; i++)
            {
                //假設tempIndex的下標的值最小
                int tempIndex = i;

                for (int j = i + 1; j < list.Count; j++)
                {
                    //如果tempIndex下標的值大于j下標的值,則記錄較小值下標j
                    if (list[tempIndex] > list[j])
                        tempIndex = j;
                }

                //最后將假想最小值跟真的最小值進行交換
                var tempData = list[tempIndex];
                list[tempIndex] = list[i];
                list[i] = tempData;
            }
            return list;
        }
    }
}

比賽結果公布:

堆排序:

要知道堆排序,首先要了解一下二叉樹的模型。

下圖就是一顆二叉樹,具體的情況我后續會分享的。

那么堆排序中有兩種情況(看上圖理解):

    大根堆:  就是說父節點要比左右孩子都要大。

    小根堆:  就是說父節點要比左右孩子都要小。

 

那么要實現堆排序,必須要做兩件事情:

   第一:構建大根堆。

           首先上圖:

           

首先這是一個無序的堆,那么我們怎樣才能構建大根堆呢?

     第一步: 首先我們發現,這個堆中有2個父節點(2,,3);

     第二步: 比較2這個父節點的兩個孩子(4,5),發現5大。

     第三步: 然后將較大的右孩子(5)跟父節點(2)進行交換,至此3的左孩子堆構建完畢,

                 如圖:

                         

     第四步: 比較第二個父節點(3)下面的左右孩子(5,1),發現左孩子5大。

     第五步: 然后父節點(3)與左孩子(5)進行交換,注意,交換后,堆可能會遭到破壞,

                 必須按照以上的步驟一,步驟二,步驟三進行重新構造堆。

           

最后構造的堆如下:

                 

 

   第二:輸出大根堆。

             至此,我們把大根堆構造出來了,那怎么輸出呢?我們做大根堆的目的就是要找出最大值,

         那么我們將堆頂(5)與堆尾(2)進行交換,然后將(5)剔除根堆,由于堆頂現在是(2),

         所以破壞了根堆,必須重新構造,構造完之后又會出現最大值,再次交換和剔除,最后也就是俺們

         要的效果了,

 

 

發現自己兄弟被別人狂毆,,堆排序再也坐不住了,決定要和快排干一場。

同樣,快排也不甘示弱,誰怕誰?

復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace HeapSort
{
    public class Program
    {
        static void Main(string[] args)
        {
            //5次比較
            for (int j = 1; j <= 5; j++)
            {
                List<int> list = new List<int>();

                //插入2w個數字
                for (int i = 0; i < 20000; i++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 100000));
                }

                Console.WriteLine("/n第" + j + "次比較:");

                Stopwatch watch = new Stopwatch();
                watch.Start();
                var result = list.OrderBy(single => single).ToList();
                watch.Stop();
                Console.WriteLine("/n快速排序耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數" + string.Join(",", result.Take(10).ToList()));

                watch = new Stopwatch();
                watch.Start();
                HeapSort(list);
                watch.Stop();
                Console.WriteLine("/n堆排序耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數" + string.Join(",", list.Take(10).ToList()));
            }

        }

        ///<summary>
/// 構建堆
///</summary>
///<param name="list">待排序的集合</param>
///<param name="parent">父節點</param>
///<param name="length">輸出根堆時剔除最大值使用</param>
        static void HeapAdjust(List<int> list, int parent, int length)
        {
            //temp保存當前父節點
            int temp = list[parent];

            //得到左孩子(這可是二叉樹的定義,大家看圖也可知道)
            int child = 2 * parent + 1;

            while (child < length)
            {
                //如果parent有右孩子,則要判斷左孩子是否小于右孩子
                if (child + 1 < length && list[child] < list[child + 1])
                    child++;

                //父親節點大于子節點,就不用做交換
                if (temp >= list[child])
                    break;

                //將較大子節點的值賦給父親節點
                list[parent] = list[child];

                //然后將子節點做為父親節點,已防止是否破壞根堆時重新構造
                parent = child;

                //找到該父親節點較小的左孩子節點
                child = 2 * parent + 1;
            }
            //最后將temp值賦給較大的子節點,以形成兩值交換
            list[parent] = temp;
        }

        ///<summary>
/// 堆排序
///</summary>
///<param name="list"></param>
        public static void HeapSort(List<int> list)
        {
            //list.Count/2-1:就是堆中父節點的個數
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                HeapAdjust(list, i, list.Count);
            }

            //最后輸出堆元素
            for (int i = list.Count - 1; i > 0; i--)
            {
                //堆頂與當前堆的第i個元素進行值對調
                int temp = list[0];
                list[0] = list[i];
                list[i] = temp;

                //因為兩值交換,可能破壞根堆,所以必須重新構造
                HeapAdjust(list, 0, i);
            }
        }
    }
}

結果公布:

堆排序此時心里很尷尬,雙雙被KO,心里想,一定要撈回面子,一定要贏,

于是堆排序提出了求“前K大問題”。(就是在海量數據中找出前幾大的數據),

快排一口答應,小意思,沒問題。

雙方商定,在2w隨機數中找出前10大的數:

復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace QuickSort
{
    public class Program
    {
        static void Main(string[] args)
        {
            //5此比較
            for (int j = 1; j <= 5; j++)
            {
                List<int> list = new List<int>();

                for (int i = 0; i < 20000; i++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(1000, 100000));
                }

                Console.WriteLine("/n第" + j + "次比較:");

                Stopwatch watch = new Stopwatch();
                watch.Start();
                var result = list.OrderByDescending(single => single).Take(10).ToList();
                watch.Stop();
                Console.WriteLine("/n快速排序求前K大耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + string.Join(",", result.Take(10).ToList()));

                watch = new Stopwatch();
                watch.Start();
                result = HeapSort(list, 10);
                watch.Stop();
                Console.WriteLine("/n堆排序求前K大耗費時間:" + watch.ElapsedMilliseconds);
                Console.WriteLine("輸出前十個數:" + string.Join(",", list.Take(10).ToList()));
            }

        }

        ///<summary>
/// 構建堆
///</summary>
///<param name="list">待排序的集合</param>
///<param name="parent">父節點</param>
///<param name="length">輸出根堆時剔除最大值使用</param>
        static void HeapAdjust(List<int> list, int parent, int length)
        {
            //temp保存當前父節點
            int temp = list[parent];

            //得到左孩子(這可是二叉樹的定義哇)
            int child = 2 * parent + 1;

            while (child < length)
            {
                //如果parent有右孩子,則要判斷左孩子是否小于右孩子
                if (child + 1 < length && list[child] < list[child + 1])
                    child++;

                //父節點大于子節點,不用做交換
                if (temp >= list[child])
                    break;

                //將較大子節點的值賦給父親節點
                list[parent] = list[child];

                //然后將子節點做為父親節點,已防止是否破壞根堆時重新構造
                parent = child;

                //找到該父節點左孩子節點
                child = 2 * parent + 1;
            }
            //最后將temp值賦給較大的子節點,以形成兩值交換
            list[parent] = temp;
        }

        ///<summary>
/// 堆排序
///</summary>
///<param name="list">待排序的集合</param>
///<param name="top">前K大</param>
///<returns></returns>
        public static List<int> HeapSort(List<int> list, int top)
        {
            List<int> topNode = new List<int>();

            //list.Count/2-1:就是堆中非葉子節點的個數
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                HeapAdjust(list, i, list.Count);
            }

            //最后輸出堆元素(求前K大)
            for (int i = list.Count - 1; i >= list.Count - top; i--)
            {
                //堆頂與當前堆的第i個元素進行值對調
                int temp = list[0];
                list[0] = list[i];
                list[i] = temp;

                //最大值加入集合
                topNode.Add(temp);

                //因為順序被打亂,必須重新構造堆
                HeapAdjust(list, 0, i);
            }
            return topNode;
        }
    }
}

求前K大的輸出結果:

最后堆排序趕緊拉著直接選擇排序一路小跑了,因為求前K大問題已經不是他原本來的目的。

ps: 直接選擇排序的時間復雜度為:O(n^2)

       堆排序的時間復雜度:O(NlogN)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品色婷婷视频| 色综合久久精品亚洲国产| 欧美老少做受xxxx高潮| 亚洲成人中文字幕| 亚洲最新在线视频| 68精品国产免费久久久久久婷婷| 亚洲精品720p| 欧美激情综合色综合啪啪五月| 韩日欧美一区二区| 伊人久久大香线蕉av一区二区| 97精品欧美一区二区三区| 久久久久久久999精品视频| 国产成人精品亚洲精品| 伊人久久久久久久久久久| 国产精品亚洲片夜色在线| 日本一区二区三区四区视频| 最近2019好看的中文字幕免费| 亚洲福利精品在线| 亚洲嫩模很污视频| 日韩av片免费在线观看| 欧美日韩中文字幕在线| 亚洲xxx视频| 一个人看的www久久| 国产亚洲欧美一区| 91精品久久久久久久久久入口| 这里只有精品视频在线| 性色av一区二区三区在线观看| 国模叶桐国产精品一区| 欧美剧在线观看| 亚洲欧美国产日韩天堂区| 欧美激情视频网站| 国产精品主播视频| 在线播放日韩精品| 国产精品www色诱视频| 高清欧美性猛交xxxx| 国产精品国模在线| 欧美另类老女人| 亚洲精品第一国产综合精品| 51精品国产黑色丝袜高跟鞋| x99av成人免费| 精品美女久久久久久免费| 亚洲欧美日韩视频一区| 日韩美女视频免费在线观看| 色悠悠国产精品| 日韩有码片在线观看| 成人激情电影一区二区| 国产精品夜色7777狼人| 亚洲一区精品电影| 亚洲va久久久噜噜噜| 久久韩剧网电视剧| 欧美最猛性xxxxx(亚洲精品)| 伊人激情综合网| 日韩电影在线观看永久视频免费网站| 中文字幕成人在线| 欧美激情一区二区三区在线视频观看| 日韩av电影中文字幕| 国产精品九九久久久久久久| 亚洲影院色在线观看免费| 国产精品久久一区| 在线成人激情黄色| 亚洲色图15p| 日韩av中文字幕在线免费观看| 一本色道久久88精品综合| 精品调教chinesegay| 成人精品aaaa网站| 亚洲精品久久久久久久久久久久| 国产午夜精品美女视频明星a级| 久久亚洲成人精品| 亚洲欧美www| 欧美成人精品在线视频| 国产一区二区三区视频| 亚洲免费av电影| 中国china体内裑精亚洲片| 欧洲成人性视频| 国产女人精品视频| 日韩视频在线免费观看| 亚洲国产天堂久久综合网| 国产精品久久久久久中文字| 欧美成人全部免费| 国产一区av在线| 国产精品偷伦视频免费观看国产| 国产一区二区三区视频在线观看| 日韩久久精品成人| 中日韩午夜理伦电影免费| 亚洲免费视频一区二区| 亚洲精品动漫100p| 久久不射热爱视频精品| 亚洲国产欧美一区二区三区同亚洲| 92福利视频午夜1000合集在线观看| 欧美性猛交99久久久久99按摩| 欧美色图在线视频| 久久久久免费精品国产| 91最新在线免费观看| 国产亚洲成av人片在线观看桃| 国产精品视频网| 亚洲电影免费观看高清完整版| 97热精品视频官网| 亚洲性视频网站| 在线日韩av观看| 亚洲欧美国产精品va在线观看| 亚洲男女自偷自拍图片另类| 欧美在线www| 最近2019中文字幕在线高清| 亚洲人成网在线播放| 中文字幕亚洲专区| 成人日韩在线电影| 欧美精品videos| 日韩av综合网站| 国产精品一区二区性色av| 久久69精品久久久久久久电影好| 日韩美女av在线免费观看| 欧美午夜视频在线观看| 国产国语videosex另类| 91成人天堂久久成人| 琪琪第一精品导航| 亚洲一区亚洲二区| 日韩免费在线视频| 国内精久久久久久久久久人| 日韩国产欧美精品一区二区三区| 国产日韩欧美夫妻视频在线观看| 中文字幕日韩精品有码视频| 日韩欧美成人精品| 亚洲人成在线播放| 97视频免费在线看| 国产热re99久久6国产精品| 91九色国产在线| 亚洲影视中文字幕| 日韩av一区在线| 国产精品丝袜久久久久久高清| 91精品国产高清久久久久久91| 91在线观看免费高清| 在线视频精品一| www.亚洲一二| 亚洲电影免费观看高清完整版| 久久久91精品国产一区不卡| 国产精品一区二区三区久久久| 久久亚洲综合国产精品99麻豆精品福利| 欧美大片在线看免费观看| 亚洲天堂网在线观看| 91在线观看免费观看| 日韩性生活视频| 国产精品男人爽免费视频1| 中文字幕亚洲欧美| 国外色69视频在线观看| 97国产精品免费视频| www.欧美三级电影.com| 欧美另类精品xxxx孕妇| 综合激情国产一区| 久久综合久久美利坚合众国| 久久久久国产视频| 日韩免费观看高清| 亚洲一区二区三区xxx视频| 色综合伊人色综合网站| 国产欧美婷婷中文| 91精品在线一区| 国产精品亚洲自拍| 日韩中文字幕国产精品| 91精品啪aⅴ在线观看国产| 国产精品情侣自拍| 日韩av电影手机在线观看| 久久成人在线视频| 97国产精品人人爽人人做| 免费99精品国产自在在线| 久久精品国产亚洲一区二区|