数据结构与算法/分治法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/li99yangg/article/details/79100762

1、用分治法设计与实现归并排序算法。

2、给定含有 n 个元素的多重集合 S,每个元素在 S 中出现的次数称为该元素的重数。多重集合 S 中重数最大的元素称为众数。例如多重集合 S={1,2,2,7,2,7,5},其中众数是 2,其重数为 3。用分治法设计并实现在多重集合中找众数及其重数的算法,要求算法的时间复杂性在坏情况下不超过 O(nlogn)。

//分治法实现归并排序

#include <iostream>

#include <string.h>

using namespace std;

#define SIZE 10

typedef struct

{

    int num;

    int freq;

}Elem;

void merge(int array[],int first,int mid,int last)//归并排序

{

    int new_arr[SIZE],i,j,k=first;//创建临时数组new_arr和ijk的初始化

    memset(new_arr,0,SIZE);//初始化new_arr数组

    for (i = first,j = mid + 1;(i <= mid)&&(j <= last);)//将原数组的前半段的第一个元素和后半段的第一个元素比较,并放入临时数组中直到某半段数组全部排序完

    {

        if(array[i] <= array[j])

            new_arr[k++] = array[i++];

        else

            new_arr[k++] = array[j++];

    }

    if(i <= mid)//如果后半段的数组先排序完,则将前半段的剩下的所有元素按顺序接到原数组的后边

        for(;i <= mid;i++)

            new_arr[k++] = array[i];

    if(j <= last)//如果前半段的数组先排序完,则将后半段的剩下的所有元素按顺序接到原数组的后边

        for(;j <= last;j++)

            new_arr[k++] = array[j];

    for(int p = first;p <=last;p++)   //将排好顺序的元素放回原数组

        array[p]=new_arr[p];

}

void merge_sort(int array[],int first,int last)//归并排序

{

    int mid = 0;//初始化mid

    if(first<last)

    {

        mid = (first + last)/2;//mid 为数组长度的一半

        merge_sort(array, first,mid);//分治法:将数组分为两段,先对前半段进行归并排序

        merge_sort(array, mid+1,last);//对后半段进行归并排序

        merge(array,first,mid,last);//再将整体进行一次归并排序

    }

}

void merge(Elem array[],int first,int mid,int last)//归并排序

{

    Elem new_arr[4];

    int i,j,k=first;//创建临时数组new_arr和ijk的初始化

    for (i = first,j = mid + 1;(i <= mid)&&(j <= last);)//将原数组的前半段的第一个元素和后半段的第一个元素比较,并放入临时数组中直到某半段数组全部排序完

    {

        if(array[i].freq <= array[j].freq)

            new_arr[k++] = array[i++];

        else

            new_arr[k++] = array[j++];

    }

    if(i <= mid)//如果后半段的数组先排序完,则将前半段的剩下的所有元素按顺序接到原数组的后边

        for(;i <= mid;i++)

            new_arr[k++] = array[i];

    if(j <= last)//如果前半段的数组先排序完,则将后半段的剩下的所有元素按顺序接到原数组的后边

        for(;j <= last;j++)

            new_arr[k++] = array[j];

    for(int p = first;p <=last;p++)   //将排好顺序的元素放回原数组

        array[p]=new_arr[p];

}

void merge_sort(Elem array[],int first,int last)//归并排序

{

    int mid = 0;//初始化mid

    if(first<last)

    {

        mid = (first + last)/2;//mid 为数组长度的一半

        merge_sort(array, first,mid);//分治法:将数组分为两段,先对前半段进行归并排序

        merge_sort(array, mid+1,last);//对后半段进行归并排序

        merge(array,first,mid,last);//再将整体进行一次归并排序

    }

}

int main()

{

    int arr[SIZE]={9,3,5,6,8,7,0,2,1,4};

    merge_sort(arr,0,9);

    for(int i = 0;i < SIZE;i++)

        cout << arr[i] << " ";

    cout << endl;

    cout<<"第二个实验:请输入一组数,返回众数及频度";

    int array[10]={1,2,3,4,1,2,3,1,2,1};

    merge_sort(array,0,9);

    Elem anoarr[4];

    for(int i = 0;i<4;i++)

    {

        anoarr[i].num = 0;

        anoarr[i].freq = 0;

    }

    int  j = 0;

    cout<<endl;

    for(int i =0;i<10;i++)

    {

        if(i == 0)

        {

            anoarr[j].freq++;

            anoarr[j].num = array[i];

        }else {

            if(array[i-1]!=array[i])

            {

                j++;

                anoarr[j].freq++;

                anoarr[j].num = array[i];

            }

            else

            {

                anoarr[j].freq++;

            }

        }

    }

    merge_sort(anoarr,0,3);

    for(int i = 0;i<4;i++)

        {

            cout<<"anoarr["<<i<<"].num="<<anoarr[i].num<<" ";

            cout<<"anoarr["<<i<<"].freq="<<anoarr[i].freq<<endl;

        }

        cout<<"众数是:"<<anoarr[3].num<<" 重度是:"<<anoarr[3].freq;

    return 0;

}


猜你喜欢

转载自blog.csdn.net/li99yangg/article/details/79100762