【2021年数据结构真题】

272 阅读3分钟

本文正在参加「金石计划」

41题

已知无向连通图G由顶点集V和边集E组成,|E| > 0,当G中度为奇数的顶点个数为不大于2的偶数时,G 存在包含所有边且长度为|E|的路径(称为EL路径)。设图G采用邻接矩阵存储,类型定义如下:

typedef struct {               // 图的定义
    int numVertices, numEdges; // 图中实际的顶点数和边数
    char VerticesList[MAXV];   // 顶点表,MAXV为已定义常量
    int Edge[MAXV][MAXV];      // 邻接矩阵
}MGraph;

请设计算法int IsExistEL(MGraph G),判断G是否存在EL路径,若存在,则返回1 ,否则返回0。要求:

⑴ 给出算法的基本设计思想。

⑵ 根据设计思想,采用C或C++语言描述算法,关键之处给出注释。

⑶ 说明你所设计算法的时间复杂度和空间复杂度。

解法一

int IsExistEL(MGraph G)
{
    int degrees[G.numVertices];
    memset(degrees, 0, sizeof(degrees));
    // 遍历无向图统计所有点的度
    for (int i = 0; i < G.numVertices; i++)
    {
        for (int j = 0; j < G.numVertices; j++)
        {
            degrees[i] += G.Edge[i][j];
        }
    }
    int count = 0;
    // 遍历degrees数组统计度为奇数的点的个数
    for (int i = 0; i < G.numVertices; i++)
    {
        if (degrees[i] % 2 != 0)
        {
            count++;
        }
    }
    // 检查度为奇数的点个数是否为0或者2
    if (count == 0 || count == 2)
    {
        return 1; // 存在EL路径
    }
    else
    {
        return 0; // 不存在EL路径
    }
}

解法二

int IsExistEL(MGraph G)(
    //采用邻接矩阵存储,判断图是否存在EL路径
    int degree,i,j,count=0;
    for(i=0;i<G.numVertices;i++){
        degree = 0;
        for (j = 0; j < G.numVertices; j++)
            degree += G.Edge[i][j]; //依次计算各个顶点的度
        if (degree % 2 != 0)
            count++; //对度为奇数的顶点计数
        }
    if (count == 0 || count == 2)
                return1            //存在EL路径,返回1;
    else return 0; //不存在EL路径,返回0
}

时间复杂度间复度:

算法需要遍历整个邻接矩阵,所以时间复杂度是 O(n),空间复杂度是 0(1)


42题 已知某排序算法如下:

void cmpCountSort(int a[], int b[], int n)
{
    int i, j, *count;
    count = (int *)malloc(sizeof(int) * n);
    //C++语言: count=new int[n];
    for (i = 0; i < n; i++)
        count[i] = 0;
    for (i = 0; i < n - 1; i++)
        for (j = i + 1; j < n; j++)
            if(a[il<alil)
                count[j]++;
            else
                count[i]++;
    for (i = 0; i < n; i++)
        b[count[il]=ali;
        free(count); //C++语言: delete count;
}

请回答下列问题。
1)若有 int a[] ={25,-10,25,10,11,19}, b[6];,则调用 cmpCountSort(a,b,6)后数组b中的内容是什么?
2) 若 a 中含有 n个元素,则算法执行过程中,元素之间的比较次数是多少?
3)该算法是稳定的吗?若是,则阐述理由;否则,修改为稳定排序算法。

解答:

cmpCountSort 算法基于计数排序的思想,对序列进行排序。
cmpCountSort 算法遍历数组中的元素,count 数组记录比对应待排序数组元素下标大的元素个数,例如,count[1]=3 的意思是数组 a 中有3 个元素比 a[1]大,即 a[1]是第4元素,a[1]的正确位置应是 b[3]。

  1. 排序结果为b[6]={-10,10,11,19,25,25}。
  2. 由代码 for(i=0; i<n-1; i++) 和 for(j=i+1; j<n; j++)可知,在循环过程中每个元素都与它后面的所有元素比较一次(即所有元素都两两比较一次),比较次数之和为(n-1)+(n-2)+····+1,故总的比较次数是n(n-1)/2。
  3. 不是。需要将程序中的 if 语修改如下:
if(a[i]<=a[j]) 
    count[j]++;
else 
    count[i]++;

如果不加等号,两个相等的元素比较时,前面元素的 count 值会加 1,导致原序列中靠前的元素在排序后的序列中处于靠后的位置。