溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

發(fā)布時(shí)間:2020-06-12 13:01:06 來源:網(wǎng)絡(luò) 閱讀:367 作者:淡淡_小孩 欄目:編程語言

一.遞歸

一.遞歸的介紹
遞歸是一種數(shù)學(xué)上分而自治的思想
A.將原問題分解為規(guī)模較小的問題進(jìn)行處理
1.分解后的問題與原問題的類型完全相同,但是規(guī)模較小
2.通過小規(guī)模問題的解,能夠輕易求得原問題的解
B.問題的分解時(shí)有限的(遞歸不能無限進(jìn)行)
1.當(dāng)邊界條件不滿足時(shí),分解問題(遞歸繼續(xù)進(jìn)行)
2.當(dāng)邊界條件滿足時(shí),直接求解(遞歸結(jié)束)
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序
C.遞歸在程序設(shè)計(jì)中的應(yīng)用
a.遞歸函數(shù)
1.函數(shù)體中存在自我調(diào)用的函數(shù)
2.遞歸函數(shù)必須有遞歸出口(邊界條件)
3.函數(shù)的無限遞歸將導(dǎo)致程序崩潰
示例:
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

int sum(unsigned int n)
{
    int ret;

    if(n==1)
    {
        ret=1;
    }
    if(n>1)
    {
        ret=n+sum(n-1);
    }

    return ret;
}

數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

int fac(unsigned int n)
{
    if(n>=3)
    {
        return fac(n-1)+fac(n-2);
    }
    if((n==1)||(n==2))
    {
        return 1;
    }

    return 0;
}

二.遞歸的應(yīng)用
單向鏈表的轉(zhuǎn)置
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

struct Node
{
    int data;
    Node* next;
};

Node* creat(int v,int len)
{
    Node* ret=NULL;
    Node* slider=NULL;

    for(int i=0;i<len;i++)
    {
        Node* n=new Node();

        n->data=v++;
        n->next=NULL;

        if(slider==NULL)
        {
            slider=n;
            ret=n;
        }
        else
        {
            slider->next=n;
            slider=n;
        }
    }

    return ret;
}

void destroy(Node* list)
{
    while(list)
    {
        Node* del=list;
        list=list->next;
        delete del;
    }
}

void print(Node* list)
{
    while(list)
    {
        cout<<list->data<<"->";
        list=list->next;
    }
    cout<<"NULL"<<endl;
}

Node* reserve(Node* list)//遞歸的實(shí)現(xiàn)
{
    Node* ret=NULL;
    if((list==NULL)||(list->next==NULL))
    {
        ret=list;
    }
    else
    {
        Node* guad=list->next;
        ret=reserve(list->next);
        guad->next=list;
        list->next=NULL;
    }
    return ret;
}

單向排序鏈表的合并
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

Node* merge(Node* list1, Node* list2)
{
  Node* ret = NULL;
  if(NULL == list1)
  {
    ret = list2;
  }
  else if(NULL == list2)
  {
    ret = list1;
  }
  else if(list1->data < list2->data)
  {
    list1->next = merge(list1->next,list2);
    ret = list1;
  }
  else
  {
    list2->next = merge(list2->next, list1);
    ret = list2;
  }
  return ret;
}

二.排序

排序的一般定義
排序時(shí)計(jì)算機(jī)內(nèi)經(jīng)常進(jìn)行的一種操作,其目的是將一組無序的數(shù)據(jù)元素調(diào)整為有序的數(shù)據(jù)元素
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序
排序的數(shù)學(xué)定義
假設(shè)含n個(gè)數(shù)據(jù)元素的序列為{R1,R2....Rn}其相應(yīng)的關(guān)鍵字序列為{K1,K2....,Kn},這些關(guān)鍵字相互之間可以進(jìn)行比較,即:在它們之間存在一個(gè)關(guān)系:Kp1<=Kp2......<=Kpn,將此固有關(guān)系將上式記錄序列重新排列為{Rp1,Rp2....,Rpn}的操作稱為排序
排序的穩(wěn)定性
如果在序列中有兩個(gè)元素r[i]和r[j],它們的關(guān)鍵字K[i]==K[j],且在排序之前,對(duì)象r[i]排在r[j]前面;如果在排序之后,對(duì)象r[i]仍在r[j]的前面,則稱這個(gè)排序方法是穩(wěn)定的,否則稱這個(gè)排序方法是不穩(wěn)定的
排序的審判
時(shí)間性能
1.關(guān)鍵性能差異體現(xiàn)在比較和交換的數(shù)量
輔助存儲(chǔ)空間‘
1.為完成排序操作需要的額外的存儲(chǔ)空間
2.必要時(shí)可以“空間換時(shí)間”
算法的實(shí)現(xiàn)復(fù)雜性
1.過于復(fù)雜的排序法可能影響可讀性和維護(hù)性
各種排序的實(shí)現(xiàn)
A.選擇排序的基本思想
每次(例如第i次,i=o,1,......n-2)從后面n-i個(gè)待排的數(shù)據(jù)元素中選出關(guān)鍵字最小的元素,作為有序元素序列第i個(gè)元素
圖示
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

 template <typename T>
        static void select(T array[],int len)
        {
            for(int i=0;i<len;i++)
            {
                int min=i;//從第i個(gè)元素開始

                for(int j=i+1;j<len;j++)//將最小值與剩下的元素進(jìn)行比較
                {
                    if(array[min]>array[j])
                    {
                        min=j;
                    }
                }
                if(min!=i)
                {
                    Swap(array[i],array[min]);

                }
                //Swap(arrar[0],arrar[min]);
            }
         }

插入排序的基本思想
當(dāng)插入第i(i>=1)個(gè)數(shù)據(jù)元素時(shí),前面的V[0],V[1],...,V[i-1]已經(jīng)排好序,這時(shí),用V[i]的關(guān)鍵字與V[i-1],V[i-2],...,V[0]關(guān)鍵字進(jìn)行比較,找到位置后將V[i]插入,原來位置上的對(duì)象向后順移
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

 template <typename T>
         static void insert(T array[],int len)
         {
             for(int i=0;i<len;i++)
             {
                 int k=i;
                 T temp=array[i];
                 for(int j=i-1;j>=0;j--)
                 {
                     if(array[j]>temp)//如果array[j]下的值大于temp,將array[j]往后移動(dòng)一位
                     {
                        array[j+1]=array[j];
                        k=j;
                     }
                     else
                     {
                         break;
                     }
                 }
                 if(k!=i)
                 {
                     array[k]=temp;
                 }
             }
         }

冒泡排序的基本思想
每次從后向前進(jìn)行(假設(shè)為第i次),j=n-1,n-1,...,i,兩兩比較V[j-1]和V[j]的關(guān)鍵字;如果發(fā)生逆序,則交換V[j-1]和V[j]
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

         template <typename T>//冒泡排序
         static void Bubble(T array[],int len)
         {
             bool exchange=true;
             for(int i=0;(i<len)&&exchange;i++)//從后往前的實(shí)現(xiàn)
             {
                 exchange=false;

                 for(int j=len-1;j>i;j--)
                 {
                     if(array[j]<array[j-1])
                     {
                        Swap(array[j-1],array[j]);
                     }
                 }
             }
         }

希爾排序的基本思想
將待排序列劃分為若干組,在每一組內(nèi)進(jìn)行插入排序,以使整個(gè)序列基本有序,然后再對(duì)整個(gè)序列進(jìn)行插入排序
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

        template <typename T>
         static void Shell(T array[],int len)
         {
             int d=len;

             do
             {
                d=d/3+1;//d為增量 d的值在排序的過程中由大到小逐漸縮小,直至最后一趟排序減為1

                for(int i=d;i<len;i+=d)
                {
                    //cout<<i;
                    int k=i;
                    T temp=array[i];
                    for(int j=i-d;j>=0;j-=d)
                    {
                        if(array[j]>temp)
                        {
                           array[j+d]=array[j];
                           k=j;
                           //cout<<k;
                        }
                        else
                        {
                            break;
                        }
                    }
                    if(k!=i)
                    {
                        array[k]=temp;
                    }
                }
             }while(d>1);
         }

歸并排序的基本思想
將兩個(gè)或兩個(gè)以上的有序序列合并成一個(gè)新的有序序列
有序序列V[0]...V[m]和V[m+1]....V[n-1]====>V[0]...V[n-1]這種歸并方法稱為2路歸并
歸并的套路
1.將3個(gè)有序序列歸并為一個(gè)新的有序序列,稱為3路歸并
2.將N個(gè)有序序列歸并為一個(gè)新的有序序列,稱為N路歸并
3.將多個(gè)有序序列歸并為一個(gè)新的有序序列,稱為多路歸并
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

         template <typename T>//歸并排序的實(shí)現(xiàn)
         static void Merge(T array[],int len)
         {
             T* helper=new T[len];//申請(qǐng)的輔助空間

             if(helper!=NULL)
             {
                 Merge(array,helper,0,len-1);
             }
         }

                template <typename T>
        static void Merge(T src[],T helper[],int begin,int mid,int end)
        {
            int i=begin;
            int j=mid+1;
            int k=begin;

            while((i<=mid)&&(j<=end))
            {
                if(src[i]<src[j])
                {
                    helper[k++]=src[i++];
                }
                else
                {
                    helper[k++]=src[j++];
                }
            }

            while(i<=mid)
            {
                helper[k++]=src[i++];
            }
            while(j<=end)
            {
                helper[k++]=src[j++];
            }

            for(i=begin;i<=end;i++)
            {
                src[i]=helper[i];
            }
        }

        template <typename T>
        static void Merge(T src[],T helper[],int begin,int end)
        {
            if(begin==end)
            {
                return;
            }
            else
            {
                int mid=(begin+end)/2;

                Merge(src,helper,begin,mid);
                Merge(src,helper,mid+1,end);
                Merge(src,helper,begin,mid,end);
            }
        }

快速排序的基本思想
任取序列在的某個(gè)數(shù)據(jù)元素作為基準(zhǔn)將整個(gè)序列劃分為左右兩個(gè)子序列
1.左側(cè)子序列在中所有元素都小于或等于基準(zhǔn)元素
2.右側(cè)子序列中所有元素都大于基準(zhǔn)元素
3.基準(zhǔn)元素排在這兩個(gè)子序列中間
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序
數(shù)據(jù)結(jié)構(gòu)-- 遞歸 排序

         template <typename T>//快速排序
         static void Quick(T array[],int len)
         {
             Quick(array,0,len-1);
         }

                 template <typename T>
        static int Partiton(T array[],int begin,int end)
        {
            T pv=array[begin];

            while(begin<end)
            {
                while((begin<end)&&(array[end]>pv))
                {
                    end--;
                }
                Swap(array[begin],array[end]);

                while((begin<end)&&(array[begin]<=pv))
                {
                    begin++;
                }
                Swap(array[begin],array[end]);
            }

            array[begin]=pv;

            return begin;
        }

        template <typename T>
        static void Quick(T array[],int begin,int end)
        {
            if(begin<end)
            {
                int pivot=Partiton(array,begin,end);

                Quick(array,begin,pivot-1);
                Quick(array,pivot+1,end);
            }
        }
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI