王道考研--》顺序表课后习题C语言代码实现(冲刺)

news2024/11/23 5:10:48

        考研是许多计算机科学专业学生追求高学历、寻求更好就业前景的途径。在考研过程中,数据结构是一个非常重要的科目,而代码实现题更是其中的难点之一。在这篇文章中,我们将探讨如何通过实现数据结构代码问题来提升考研成绩。无论您是否有编程经验,本文将为您提供一些简单但实用的技巧,帮助您应对考研中遇到的数据结构题目。让我们一起踏上这个挑战性的学习旅程吧!

为了照顾一些小白,博主会在开篇也就是本文章尽量将一些细枝末节的东西讲解清楚其代表的含义是什么,后期的一些文章可能就不会像本文这么啰嗦了,大家按需学习即可!

目录

初始C语言

初识顺序表

顺序表的两种写法

第一题)删除顺序表中最小值

第二题)逆置数据元素

第三题)删除数组中指定元素的所有出现值

第四题)删除指定范围值

第五题)删除重复值

第六题)合并两个顺序表

第七题)逆置顺序表中指定范围元素

第八题)折半查找指定元素

第九题)找数组中未出现的最小正整数

第十题 )寻找主元素


初始C语言

        c语言运行的第一步:就是导入我们的预处理指令(俗称头文件),程序可以使用其中定义的函数和类型,而不需要自己实现这些功能。在本案例中我们需要导入两个头文件 stdio.hstdlib.h ,其中stdio.h是最最常用的头文件,机会你要编写c程序,百分百需要使用它。

//stdio.h 提供了输入输出函数(如printf和scanf)以及相关的类型和常量的定义。
#include <stdio.h>
//stdlib.h 提供了一些通用的函数(如malloc和free),用于内存分配、进程控制和其他常见任务。
#include <stdlib.h>

        c语言运行的第二步:编写入口函数,它是每个程序必须包含的部分。它表示程序的执行从这里开始。在main函数中,你可以编写程序的主要逻辑和功能。在函数体内,可以使用各种语句和表达式来完成所需的任务,例如变量声明、函数调用和控制流语句等。

注意:在C语言中,main函数是唯一一个不可省略的函数,它是程序的起点和终点。程序从main函数开始执行,执行完main函数后,程序结束。

int main() {
	// 逻辑代码执行
}

        c语言运行的第三步:在主函数体中编写处理输入输出的代码,与用户进行交互,调用其他函数、模块或库来实现特定功能,进行算术运算、逻辑判断等等。主函数体是整个程序的核心部分,它负责协调和调度其他代码来实现程序的功能。

#include <stdio.h>

// 主函数体区域

int main(){

}

初识顺序表

        顺序表就是一种基于数组实现的线性数据结构。顺序表中的元素是按照在内存中的物理顺序进行连续存储的,因此可以通过下标来随机访问元素。我们可以把数组看做是一种最简单的顺序表,它只包含元素的类型和一个连续的内存块。

        顺序表和数组不完全相同。数组是一种静态数据结构,在声明数组时需要指定数组的大小,而且数组的大小不能动态增加或缩小。而顺序表则可以通过动态内存分配进行动态增加或缩小,因此顺序表是一种动态数据结构

顺序表有两种常见的实现方式:静态顺序表动态顺序表

        静态顺序表(Static Array):静态顺序表使用静态数组来表示,其大小在编译时就确定了,无法动态调整。静态顺序表需要提前指定一个固定的最大容量,如果超过了该容量,就无法添加新的元素。静态顺序表的优点是操作简单,直接利用数组的随机访问特性,但缺点是容量固定,无法动态扩展大小。

下列代码中定义了一个长度为5的静态数组arr,并初始化了其中的元素。由于静态数组在编译时就确定了大小,因此其大小无法动态调整。

#include <stdio.h>

#define MAX_SIZE 5

int main() {
    // 静态数组初始化,分配了 MAX_SIZE 个元素的空间
    int arr[MAX_SIZE] = {1, 2, 3, 4, 5};

    // 遍历数组并输出每个元素
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

        动态顺序表(Dynamic Array):动态顺序表使用动态内存分配来表示,其大小可以根据需要动态增长或缩小。动态顺序表最常见的实现是通过使用malloc()和realloc()函数来动态分配和重新分配内存空间。动态顺序表的优点是可以根据需求灵活地改变大小,但缺点是相比静态顺序表,多了内存分配和释放的开销。

下列代码中使用malloc()函数在堆内存中申请了一个长度为5的动态数组arr,并初始化了其中的元素。由于动态数组使用堆内存分配,在运行时可以通过realloc()函数动态地调整数组大小。代码中使用realloc()函数将原本长度为5的数组扩容为长度为10的数组,并向其中添加新元素。最后,使用free()函数释放动态数组占用的内存。

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 动态数组初始化,开始时分配了 5 个元素的空间
    int* arr = (int*)malloc(sizeof(int) * 5);
    if (arr == NULL) {
        printf("动态数组分配内存失败\n");
        return -1;
    }

    // 遍历数组并输出每个元素
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 动态调整数组大小
    int* new_arr = (int*)realloc(arr, sizeof(int) * 10);
    if (new_arr == NULL) {
        printf("动态数组重新分配内存失败\n");
        free(arr);
        return -1;
    }
    arr = new_arr;

    // 向数组中添加新元素
    for (int i = 5; i < 10; i++) {
        arr[i] = i + 1;
    }

    // 遍历扩容后的数组并输出每个元素
    for (int i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 释放动态数组占用的内存
    free(arr);

    return 0;
}

顺序表的两种写法

在c语言中实现顺序表的方式有两种:

使用数组来存储数据,例如:

// 这里的 a 数组即是一个顺序表,其下标从 0 到 MAXSIZE - 1
int a[MAXSIZE];

// 可以通过下标访问其中的元素,例如:
int x = a[0]; // 获取第一个元素
a[1] = 2;     // 修改第二个元素

使用结构体来存储顺序表中的数据以及长度信息,例如:

// 这里的 SeqList 即是一个顺序表类型,其中 data 数组存储了顺序表中的元素,length 变量表示顺序表的长度。
typedef struct {
    int data[MAXSIZE];
    int length;
} SeqList;

// 可以通过操作结构体成员来访问和修改顺序表中的元素和长度信息,例如:
SeqList list;
list.data[0] = 1;
list.data[1] = 2;
list.length = 2;

两种方式各有优缺点

使用数组实现的顺序表不需要定义额外的数据类型,对于简单的操作来说可能更加方便,但是对于需要对顺序表进行多种操作(例如插入、删除、查找等)时,使用结构体实现的顺序表会更加灵活和易于维护。

接下来我会在前五题中使用数组实现顺序表,后五题中使用结构体实现顺序表。

第一题)删除顺序表中最小值

从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删除元素的值。空出的位置有最后一个元素填补,若顺序表为空则显示出错信息并退出运行。

实现思路如下

首先:在主函数中,通过用户输入获取了数组的长度 n,并动态分配了一个长度为 n 的整型数组 arr 来存储用户输入的元素值,使用 for 循环依次读取用户输入的元素值,并将其保存在数组 arr 中。

接着:通过调用 delMin() 函数来删除顺序表中的最小元素。该函数接受数组 arr 和数组长度 n 的指针作为参数。在 delMin() 函数中,首先判断数组长度是否为 0,如果是,则打印 "数组为空" 的提示信息,并返回一个-1。如果数组长度不为 0,那么就遍历数组寻找最小元素的位置,并将最小元素与数组末尾的元素交换位置。然后将数组长度减一,表示成功删除了一个元素。最后,返回被删除的最小元素。

然后:我们回到主函数将 delMin() 函数返回的最小元素保存在变量 min 中,并输出 "删除的最小值为:" 的提示信息以及最小值的具体数值。

最后:使用 for 循环输出删除最小元素后的顺序表,即数组 arr 的元素。同时,释放动态分配的内存,并将指针 arr 赋值为 NULL,以避免出现野指针问题。

#include <stdio.h>
#include <stdlib.h>

int delMin(int* arr, int* len) {
    if (*len == 0) {
        printf("数组为空\n");
        return -1;
    }
    int min = arr[0], minPos = 0;
    for (int i = 1; i < *len; i++) {
        if (min > arr[i]) {
            min = arr[i];
            minPos = i;
        }
    }
    arr[minPos] = arr[*len - 1];
    (*len)--;
    // 返回被删除的最小元素
    return min;
}

int main() {
    int n;
    printf("请输入数组长度的个数,n=");
    scanf_s("%d", &n);

    if (n <= 0) {
        printf("数组长度必须大于0\n");
        return 0;
    }

    int* arr = (int*)malloc(sizeof(int) * n);
    printf("请输入数组的元素值:\n");
    for (int i = 0; i < n; i++) {
        scanf_s("%d", arr + i);
    }
    printf("原始顺序表:");
    for (int i = 0; i < n; i++) {
        printf_s("%d ", *(arr + i));
    }
    printf("\n");
    int min = delMin(arr, &n);
    printf("删除的最小值为:%d\n", min);
    printf("删除后顺序表:");
    for (int i = 0; i < n; i++) {
        printf_s("%d ", arr[i]);
    }

    free(arr);  // 释放动态分配的内存
    arr = NULL; // 避免野指针问题
    return 0;
}

执行代码结果展示如下:

第二题)逆置数据元素

设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)

实现思路如下

首先:在主函数中,通过用户输入获取了数组的长度 n,并动态分配了一个长度为 n 的整型数组 arr 来存储用户输入的元素值。使用 for 循环依次读取用户输入的元素值,并将其保存在数组 arr 中。

接着:设置 reserve() 函数,传入数组和数组长度的地址,实现对数组的逆置操作。在 reserve() 函数内部,首先判断数组长度是否为 0,如果是则打印数组为空的提示信息。接下来,使用一个循环遍历数组的前半部分,并通过交换元素的方式实现逆置操作。

然后:我们回到主函数调用 reserve() 函数

最后:再次使用 printf_s() 打印逆置后的元素。同时,使用 free() 函数释放动态分配的内存空间,将指针 arr 设置为 NULL,以避免悬挂指针的问题。返回 0,表示程序正常结束。

#include <stdio.h>
#include <stdlib.h>

void reserve(int* arr, int* len) {
	if (!*len) {
		printf_s("数组为空\n");
	}
	int tmp; // 定义一个暂存空间
	for (int i = 0; i < *len/2; i++)
	{	
		tmp = *(arr + i);
		*(arr + i) = *(arr + *len - i - 1);
		*(arr + *len - i - 1) = tmp;
	}
}

int main() {
	int n; // 定义数组的长度
	printf_s("请输入数组的长度,n=");
	scanf_s("%d", &n);
	if (n <= 0) {
		printf("数组长度必须大于0\n");
		return 0;
	}
	int* arr = (int*)malloc(sizeof(int) * n); // 动态分配数据空间
	printf_s("请输入数组的元素:\n");
	for (int i = 0; i < n; i++)
	{
		scanf_s("%d", arr + i);
	}
	printf_s("未逆置之前的元素:");
	for (int i = 0; i < n; i++)
	{
		printf_s("%d", arr[i]);
	}
	reserve(arr, &n);
	printf_s("\n逆置之后的元素:");
	for (int i = 0; i < n; i++)
	{
		printf_s("%d", arr[i]);
	}
	free(arr);
	arr = NULL;
	return 0;
}

执行代码结果展示如下: 

第三题)删除数组中指定元素的所有出现值

对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。

实现思路如下

首先:通过 scanf_s() 函数获取用户输入的数组长度 n。

接着:使用动态内存分配函数 malloc() 为数组分配内存空间,分配大小为 sizeof(int) * n。

然后:使用一个循环通过 scanf_s() 获取用户输入的元素,并将其存储到数组中。在 main() 函数中调用 delX() 函数,传入数组、数组长度和待删除的元素 x。在 delX() 函数中,使用两个指针 i 和 k 来追踪数组的索引和删除元素的总数。通过遍历数组,如果找到等于 x 的元素,则增加 k 的计数;否则,将当前元素移动到数组的正确位置。

最后:使用一个循环打印出删除元素之后的数组内容,遍历范围是 n - k,因为前 n - k 个元素是删除元素操作之后仍然存在的元素。返回 0,表示程序正常结束。

#include <stdio.h>
#include <stdlib.h>

int delX(int* arr, int* len, int x) {
	int k = 0, i = 0; // 定义要删除元素的总数m,和要删除的下标i
	while (i < *len) {
		if (*(arr + i) == x) {
			k++;
		}
		else {
			*(arr + i - k) = *(arr + i);
		}
		i++;
	}
	for (int i = *len - k; i < *len; i++)
	{
		*(arr + i) = NULL;
	}
	return k;
}

int main() {
	int n, m; // 定义数组的长度和要删除的元素
	printf_s("请输入数据的长度:");
	scanf_s("%d", &n);
	int* arr = (int*)malloc(sizeof(int) * n);
	printf_s("请输入数组元素:");
	for (int i = 0; i < n; i++)
	{
		scanf_s("%d", arr + i);
	}
	printf_s("请输入要删除的元素:");
	scanf_s("%d", &m);
	int k = delX(arr, &n, m);
	printf_s("最终的结果:");
	for (int i = 0; i < n - k; i++)
	{
		printf_s("%d", *(arr + i));
	}
	free(arr);
	arr = NULL;
	return 0;
}

执行代码结果展示如下: 

第四题)删除指定范围值

从有序顺序表中删除其值在给定值 s 与 t 之间(要求 s < t)的所有元素,如果 s 或 t 不合理或顺序表为空,则显示出错信息并退出运行。

实现思路如下

首先:在主函数中获取用户输入的数组长度,并分配相应大小的内存空间用于存储数组元素,通过循环依次获取用户输入的每个数组元素。

接着:使用一个循环取用户输入的删除区间的起始和终止位置,并对输入进行合法性判断,如果起始位置大于终止位置,则重新输入。

然后:函数 deletePoint 接收传入的数组 arr、起始位置 m、终止位置 k 和数组长度 len。如果起始位置大于等于终止位置或者数组长度为 0,说明输入的删除区间不合法或者顺序表为空,函数会打印相应的错误提示并返回。函数使用两个循环找到第一个大于等于 m 的元素的位置 i 和第一个小于等于 k 的元素的位置 t。函数使用一个循环将从位置 t 开始到数组末尾的元素覆盖到位置 i 开始的元素,实现了删除指定区间范围内的元素。

最后:调用 deletePoint 函数删除指定区间范围内的元素,并释放动态分配的内存空间。

#include <stdio.h>
#include <stdlib.h>

void deletePoint(int* arr, int m, int k, int len) {
    if (m >= k || len == 0) {
        printf_s("输入的删除区间不合法或顺序表为空!");
        return;
    }
    int i, t;
    for (i = 0; i < len && *(arr + i) < m; i++); // 找到第一个大于等于m的元素
    if (i >= len) return;
    for (t = i; t < len && *(arr + t) <= k; t++); // 找到第一个小于等于t的元素

    for (; t < len; i++, t++) *(arr + i) = *(arr + t);
    printf_s("当前数组为:");
    for (int j = 0; j < i; j++) printf_s("%d ", *(arr + j));
}

int main() {
    int n;
    printf_s("请输入数据的长度:");
    scanf_s("%d", &n);
    printf_s("请输入数组的元素:");
    int* arr = (int*)malloc(sizeof(int) * n);
    for (int i = 0; i < n; i++)
    {
        scanf_s("%d", arr + i);
    }
    // 给定要删除元素的区间范围
    int m, k;
    do
    {
        printf_s("请输入要删除的数组元素起始范围:");
        scanf_s("%d", &m);
        printf_s("请输入要删除的数组元素终止范围:");
        scanf_s("%d", &k);
    } while (m > k); // 如果 m > k 的话需要进行重新输入
    deletePoint(arr, m, k, n);

    free(arr); // 动态分配的内存需要手动释放
    return 0;
}

执行代码结果展示如下: 

第五题)删除重复值

从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不相同。

实现思路如下

首先:在函数 deleteRepitition 中,通过循环遍历数组中的元素,对于每个元素,判断其与后一个元素是否相等,如果不相等,则将该元素保留。使用变量 k 记录保留下来的元素数量,并将这些元素逐个放回原数组中。

接着:在最后一个判断中,判断最后两个元素是否相等,如果相等,则将最后一个元素也保留下来。

然后:在主函数 main 中,定义了一个数组 arr 并初始化,获取其长度 len。之后,调用 deleteRepitition 函数删除重复元素,得到新的数组长度 len。最后,使用循环打印删除重复元素后的数组内容。

最后:整个程序结束并返回 0。

#include <stdio.h>

int deleteRepitition(int* arr, int len) {
	int k = 0; // 用来记录下标
	for (int i = 0; i < len; i++)
	{
		if (*(arr + i) - *(arr + i + 1)) {
			*(arr + k++) = *(arr + i);
		}
	}
	if (*(arr + len - 1) == *(arr + len)) {
		*(arr + k++) = *(arr + len - 1);
	}
	return k;
}

int main() {
	int arr[] = { 1,1,2,2,2,3,3,4,5 };// 定义一个数组
	int len = sizeof(arr) / sizeof(int);
	len = deleteRepitition(arr, len);
	for (int i = 0; i < len; i++) printf_s("%d", *(arr + i));
	return 0;
}

执行代码结果展示如下: 

第六题)合并两个顺序表

将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

实现思路如下

首先:定义了一个SeqList结构体表示顺序表,包含元素数组data和长度length。

接着:定义了一个Merge函数,该函数接受两个有序顺序表L1和L2作为参数,返回一个新的合并后的有序顺序表L3。实现思路是创建一个新的顺序表L3,然后使用i、j、k三个变量分别表示L1、L2、L3中元素的索引,将L1和L2中较小的元素依次放入L3中,最后将剩余的元素放入L3中。

然后:在main函数中,读入L1和L2的长度以及元素,调用Merge函数对L1和L2进行合并,最后输出合并后的有序顺序表L3中的元素。

最后:程序结束。

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100

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

// 合并两个有序顺序表为一个新的有序顺序表
SeqList Merge(SeqList L1, SeqList L2) {
    SeqList L3;
    int i = 0, j = 0, k = 0;

    while (i < L1.length && j < L2.length) {
        if (L1.data[i] <= L2.data[j]) {
            L3.data[k++] = L1.data[i++];
        }
        else {
            L3.data[k++] = L2.data[j++];
        }
    }

    while (i < L1.length) {
        L3.data[k++] = L1.data[i++];
    }

    while (j < L2.length) {
        L3.data[k++] = L2.data[j++];
    }

    L3.length = k;
    return L3;
}

int main() {
    int n1, n2;
    SeqList L1, L2, L3;
    printf("请输入 L1 的长度:");
    scanf_s("%d", &n1);
    printf("请按升序输入 %d 个元素:", n1);
    for (int i = 0; i < n1; i++) {
        scanf_s("%d", &L1.data[i]);
    }
    L1.length = n1;

    printf("请输入 L2 的长度:");
    scanf_s("%d", &n2);
    printf("请按升序输入 %d 个元素:", n2);
    for (int i = 0; i < n2; i++) {
        scanf_s("%d", &L2.data[i]);
    }
    L2.length = n2;

    L3 = Merge(L1, L2);
    printf("合并后的顺序表为:\n");
    for (int i = 0; i < L3.length; i++) {
        printf("%d ", L3.data[i]);
    }
    printf("\n");

    return 0;
}

执行代码结果展示如下: 

第七题)逆置顺序表中指定范围元素

已知在一维数组A[m+n]中依次存放两个线性表,试编写一个函数,将数组中的两个顺序表的位置互换,即将后一个顺序表放在前一个顺序表的前面。

实现思路如下

首先:代码定义了一个结构体 SeqList 用于表示顺序表,包括顺序表元素和长度。

接着:在 SwapSeqList 函数中,首先进行参数的合法性检查,然后使用动态内存分配创建临时数组,将前面部分的顺序表元素暂存到临时数组中,接着将后面的顺序表元素移到前面,最后将临时数组中的元素移动到后面的顺序表。

然后:在 main 函数中,首先获取用户输入的两个顺序表的长度,然后分配内存空间存储顺序表元素,接着依次获取用户输入的元素,调用 SwapSeqList 函数进行顺序表元素交换,并输出交换后的顺序表。

最后:释放动态分配的内存空间,程序结束。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int* elements; // 顺序表元素
    int length;    // 顺序表长度
} SeqList;

void SwapSeqList(SeqList* list, int m, int n) {
    if (m <= 0 || n <= 0 || list->length < m + n) {
        printf_s("输入参数错误\n");
        return;
    }

    // 创建一个临时数组,用于暂存前面的顺序表
    int* temp = (int*)malloc(m * sizeof(int));
    if (temp == NULL) {
        printf_s("内存分配失败\n");
        return;
    }
    for (int i = 0; i < m; i++) {
        temp[i] = list->elements[i];
    }

    // 将后面的顺序表移到前面
    for (int i = 0; i < list->length - m; i++) {
        list->elements[i] = list->elements[i + m];
    }

    // 将临时数组中的元素移到后面的顺序表
    for (int i = 0; i < m; i++) {
        list->elements[list->length - m + i] = temp[i];
    }

    free(temp);
}

int main() {
    int m, n;
    printf_s("请输入第一个顺序表的长度:");
    scanf_s("%d", &m);
    printf_s("请输入第二个顺序表的长度:");
    scanf_s("%d", &n);

    if (m <= 0 || n <= 0) {
        printf_s("输入参数错误\n");
        return 1;
    }

    SeqList list;
    list.length = m + n;
    list.elements = (int*)malloc(list.length * sizeof(int));  // 使用动态内存分配
    if (list.elements == NULL) {
        printf_s("内存分配失败\n");
        return 1;
    }

    printf_s("请输入%d个元素作为第一个顺序表:", m);
    for (int i = 0; i < m; i++) {
        scanf_s("%d", &list.elements[i]);
    }

    printf_s("请输入%d个元素作为第二个顺序表:", n);
    for (int i = 0; i < n; i++) {
        scanf_s("%d", &list.elements[m + i]);
    }

    SwapSeqList(&list, m, n);

    printf_s("交换后的顺序表为:");
    for (int i = 0; i < list.length; i++) {
        printf_s("%d ", list.elements[i]);
    }

    free(list.elements);  // 释放动态分配的内存
    return 0;
}

执行代码结果展示如下:

第八题)折半查找指定元素

线性表中的元素递增有序且按顺序存储于计算机内。要求设计一算法,完成用最少的时间在表中查找数值为 x 的元素,若找到则将其与后继元素位置相交换,若找不到则将其插入表中并使表中元素仍递增有序。

实现思路如下

首先:代码定义了顺序表的数据结构SeqList,包括元素数组指针、当前长度和最大容量,并初始化了顺序表。

接着:在SearchAndInsertOrSwap函数中,实现了对顺序表的查找、插入或交换操作。遍历顺序表元素,找到相等元素时进行交换操作,未找到相等元素时找到大于该元素的位置并插入。

然后:在main函数中,首先让用户输入顺序表的长度,然后依次输入顺序表的元素,并且调用SearchAndInsertOrSwap函数对顺序表进行操作。

最后:输出操作后的顺序表,并释放动态分配的内存。

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100 // 定义顺序表的最大长度

typedef struct {
    int* elements; // 顺序表元素
    int length;    // 顺序表当前长度
    int capacity;  // 顺序表最大容量
} SeqList;

// 初始化顺序表
void InitSeqList(SeqList* list, int maxSize) {
    list->elements = (int*)malloc(maxSize * sizeof(int));
    if (list->elements == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    list->length = 0;
    list->capacity = maxSize;
}

// 顺序表查找并插入或交换元素
void SearchAndInsertOrSwap(SeqList* list, int x) {
    int i;
    for (i = 0; i < list->length; i++) {
        if (list->elements[i] == x) { // 找到相等元素
            if (i < list->length - 1) { // 不是最后一个元素
                int temp = list->elements[i];
                list->elements[i] = list->elements[i + 1];
                list->elements[i + 1] = temp;
                return;
            }
            else {
                printf("已经是最后一个元素,无法交换\n");
                return;
            }
        }
        else if (list->elements[i] > x) { // 找到大于x的元素位置
            int j;
            for (j = list->length; j > i; j--) {
                list->elements[j] = list->elements[j - 1]; // 元素后移
            }
            list->elements[i] = x; // 插入x
            list->length++; // 长度增加
            return;
        }
    }
    if (i == list->length) { // 未找到相等元素且未插入
        list->elements[i] = x; // 直接插入末尾
        list->length++; // 长度增加
    }
}

// 打印顺序表
void PrintSeqList(SeqList* list) {
    for (int i = 0; i < list->length; i++) {
        printf("%d ", list->elements[i]);
    }
    printf("\n");
}

int main() {
    SeqList list;
    int size;
    printf("请输入顺序表的长度:");
    scanf_s("%d", &size);
    InitSeqList(&list, size);

    printf("请输入顺序表的元素:");
    for (int i = 0; i < size; i++) {
        scanf_s("%d", &list.elements[i]);
        list.length++;
    }

    int x;
    printf("请输入要查找/插入/交换的元素:");
    scanf_s("%d", &x);

    SearchAndInsertOrSwap(&list, x);

    printf("操作后的顺序表为:");
    PrintSeqList(&list);

    free(list.elements); // 释放动态分配的内存
    return 0;
}

执行代码结果展示如下:

第九题)找数组中未出现的最小正整数

给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数,例如,数据{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。

实现思路如下

首先:我们定义了一个名为SeqList的结构体,用于表示顺序表,其中包含了元素数组、当前长度和最大容量等信息。

接着:在InitSeqList函数中,我们实现了对顺序表的初始化操作,包括动态分配内存、设置初始长度和容量等。

然后:我们实现了FindSmallestPositive函数,用于找出数组中未出现的最小正整数的算法。该算法通过遍历数组,并通过交换元素的方式,使得每个正整数在数组中处于正确的位置。

最后:在main函数中,我们进行了用户输入数组长度和元素的操作,并调用了InitSeqList和FindSmallestPositive函数来完成整个流程。最后记得调用FreeSeqList来释放动态分配的内存。

#include <stdio.h>
#include <stdlib.h>

// 定义顺序表的最大长度
#define MAXSIZE 100 

// 顺序表结构体
typedef struct {
    int* elements; // 顺序表元素
    int length;    // 顺序表当前长度
    int capacity;  // 顺序表最大容量
} SeqList;

// 初始化顺序表
extern void InitSeqList(SeqList* list, int maxSize) {
    list->elements = (int*)malloc(maxSize * sizeof(int));
    if (list->elements == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    list->length = 0;
    list->capacity = maxSize;
}

// 释放顺序表占用的内存
void FreeSeqList(SeqList* list) {
    free(list->elements);
}

// 找出数组中未出现的最小正整数
int FindSmallestPositive(SeqList* list) {
    int i;
    for (i = 0; i < list->length; i++) {
        while (list->elements[i] > 0 && list->elements[i] <= list->length && list->elements[list->elements[i] - 1] != list->elements[i]) {
            int temp = list->elements[i];
            list->elements[i] = list->elements[temp - 1];
            list->elements[temp - 1] = temp;
        }
    }
    for (i = 0; i < list->length; i++) {
        if (list->elements[i] != i + 1) {
            return i + 1;
        }
    }
    return list->length + 1;
}

int main() {
    SeqList list;
    int n;
    printf("请输入数组的长度:");
    scanf_s("%d", &n);
    InitSeqList(&list, n);

    printf("请输入数组的元素:");
    for (int i = 0; i < n; i++) {
        scanf_s("%d", &list.elements[i]);
        list.length++;
    }

    int result = FindSmallestPositive(&list);
    printf("数组中未出现的最小正整数是:%d\n", result);

    FreeSeqList(&list); // 释放动态分配的内存
    return 0;
}

执行代码结果展示如下:

第十题 )寻找主元素

若一个整数序列中有过半相同元素,则称其为主元素,设计算法找出数组A的主元素,若存在主元素则输出,否则返回 -1。

实现思路如下

首先:我们定义了一个名为SeqList的结构体,用于存储顺序表的元素、当前长度和最大容量,并且定义了初始化顺序表和释放内存的函数。

接着:在FindMajorityElement函数中,我们使用Boyer-Moore投票算法来查找数组A的主元素,通过两次遍历数组,一次找出候选主元素,一次验证候选主元素是否为真正的主元素。

然后:在main函数中,我们首先接收用户输入的数组长度,并初始化顺序表。然后,依次接收用户输入的数组元素,并调用FindMajorityElement函数来查找主元素,并输出结果。

最后:我们释放了动态分配的内存,确保程序运行结束时没有内存泄漏。

#include <stdio.h>
#include <stdlib.h>

// 定义顺序表的最大长度
#define MAXSIZE 100 

// 顺序表结构体
typedef struct {
    int* elements; // 顺序表元素
    int length;    // 顺序表当前长度
    int capacity;  // 顺序表最大容量
} SeqList;

// 初始化顺序表
void InitSeqList(SeqList* list, int maxSize) {
    list->elements = (int*)malloc(maxSize * sizeof(int));
    if (list->elements == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    list->length = 0;
    list->capacity = maxSize;
}

// 释放顺序表占用的内存
void FreeSeqList(SeqList* list) {
    free(list->elements);
}

// 查找数组A的主元素
int FindMajorityElement(SeqList* list) {
    int candidate = 0;
    int count = 0;
    for (int i = 0; i < list->length; i++) {
        if (count == 0) {
            candidate = list->elements[i];
            count = 1;
        }
        else if (list->elements[i] == candidate) {
            count++;
        }
        else {
            count--;
        }
    }

    count = 0;
    for (int i = 0; i < list->length; i++) {
        if (list->elements[i] == candidate) {
            count++;
        }
    }

    if (count > list->length / 2) {
        return candidate;
    }
    else {
        return -1;
    }
}

int main() {
    SeqList list;
    int n;
    printf("请输入数组的长度:");
    scanf_s("%d", &n);
    InitSeqList(&list, n);

    printf("请输入数组的元素:");
    for (int i = 0; i < n; i++) {
        scanf_s("%d", &list.elements[i]);
        list.length++;
    }

    int result = FindMajorityElement(&list);
    if (result != -1) {
        printf("数组的主元素是:%d\n", result);
    }
    else {
        printf("数组没有主元素\n");
    }

    FreeSeqList(&list); // 释放动态分配的内存
    return 0;
}

执行代码结果展示如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1182196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#中LINQtoSQL只能在.NetFramework下使用,不能在.net 的默认安装下使用

目录 一、在net7.0下无法实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 二、在.NetFramework4.8下成功实现LINQtoSQL 1.VS上建立数据库连接 2.VS上创建LINQtoSQL 三、结论 四、理由 本文是个人观点&#xff0c;因为我百般努力在.net7.0下无法实现LINQtoSQL的…

vr地铁消防虚拟逃生自救系统降低财产及人员伤害

无论是在公共场所还是在家中&#xff0c;火灾都是一种常见的突发事件。这往往会严重影响到人们的财产和生命安全。因此&#xff0c;如何预防火灾和安全逃生就成为了非常重要的话题。这款VR模拟火灾疏散逃生系统&#xff0c;帮助人们了解火灾逃生的技巧以及正确的应对方法。 以传…

【仙逆】尸阴宗秘密揭露,王林差点被夺舍,修仙恐怖消息曝光

Hello,小伙伴们&#xff0c;我是小郑继续为大家深度解析国漫资讯。 深度爆料&#xff0c;《仙逆》国漫第九话最新剧情&#xff0c;尸阴宗表面上令人敬畏&#xff0c;但背后却隐藏着不为人知的秘密。这个宗门暗地里为受伤或死亡的强大修真者提供夺舍容器&#xff0c;帮助他们获…

基础课24——开放域QA问答

早期的对话机器人通常采用基于规则的开放问答系统。这种系统依赖于专家系统的语义模板&#xff0c;即根据预先定义的模板来匹配和回答问题。这种方法的优点是准确性相对较高&#xff0c;因为它是基于人类专家的知识和经验来设计的。然而&#xff0c;这种系统的可扩展性和灵活性…

Linux程序的地址空间

Linux程序的地址空间 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容深刻理解了什么程序或者进程的地址…

2000-2021年全国各省市城乡平均受教育年限数据(分城镇和农村)

2000-2021年全国各省市城乡平均受教育年限数据&#xff08;分城镇和农村&#xff09; 1、时间&#xff1a;2000-2021年 2、范围&#xff1a;全国及31省 3、来源&#xff1a;人口与就业统计年鉴 4、指标包括&#xff1a;城乡平均受教育年限 、6岁以上总人口 未上过学、…

【手把手教你】训练YOLOv8分割模型

1.下载文件 在github上下载YOLOV8模型的文件&#xff0c;搜索yolov8&#xff0c;star最多这个就是 2. 准备环境 环境要求python>3.8&#xff0c;PyTorch>1.8&#xff0c;自行安装ptyorch环境即可 2. 制作数据集 制作数据集&#xff0c;需要使用labelme这个包&#…

跨境电商,用指纹浏览器还是VPS?有何区别?

目前做跨境电商的小伙伴基本都是选择vps或者指纹浏览器来防关联。不过随着指纹浏览器的普及&#xff0c;越来越多人选择使用指纹浏览器&#xff0c;还没了解过指纹浏览器的小伙伴可能还在犹豫&#xff0c;vps和指纹浏览器到底哪个更好呢&#xff1f; Vps就是一个虚拟服务器&…

超级英雄云计算的技术之旅

超级英雄云计算的技术之旅 超级英雄云计算的技术之旅摘要引言可变参数&#xff1a;Java的超级工具可变参数的用途1. 编写通用工具方法2. 构建日志记录工具3. 构建数据验证工具 云计算在智能家居中的应用1. 远程控制智能设备2. 数据分析和智能决策3. 安全和隐私4. 智能家居应用开…

视频监控管理平台EasyCVR定制算法如何操作?包含哪些?

视频监控平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多路视频流&#xff0c;也能支持视…

猫主食罐头哪家好?最受欢迎的猫主食罐头Top5推荐!

亲爱的猫咪主人们&#xff0c;你是否曾为挑选适合猫咪的猫罐头品牌而感到困惑&#xff1f;我理解你们的困扰&#xff01;当初作为养猫新手的我&#xff0c;也深感这个问题不易解决。 猫咪是如此治愈我们的宠物&#xff0c;让我们沉浸在幸福中&#xff0c;因此我经常流会去各种…

未来已来,“码”上见证---通义灵码

为了撰写一份关于通义灵码的产品测评&#xff0c;我将构建一个基于提供的产品介绍和评测内容要求的框架给大家介绍这款产品。 功能使用维度 代码智能生成 使用场景&#xff1a;开发中遇到需要编写新功能、单元测试、或对现有代码进行注释时。 使用效果&#xff1a;预期通义灵…

Web服务器的搭建

网站需求&#xff1a; 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个网站目录分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于www.openlab.com/student 网站访问学生信息&#xff0c;www.openlab.com/data网站访问教…

Harmony OS—UIAbility的使用

概述 UIAbility是一种包含用户界面的应用组件&#xff0c;主要用于和用户进行交互。UIAbility也是系统调度的单元&#xff0c;为应用提供窗口在其中绘制界面。一个应用可以有一个UIAbility&#xff0c;也可以有多个UIAbility&#xff0c;类似于Android 的 Activity&#xff0c…

14.序列化和文件的输入/输出 保存对象

14.1 保存对象状态 你已经奏出完美的乐章&#xff0c;现在会想把它储存起来。你可以抓个文房四宝把它记下来&#xff0c;但也可以按下储存按钮(或按下File菜单上的Save)。然后你帮文件命名&#xff0c;并希望这个文件不会让屏幕变成蓝色的画面。 储存状态的选择有很多种&…

批量迁移redis实例的key

我们知道migrate 命令可以迁移redis的多个key&#xff0c;但是如果redis的key有非常多&#xff0c;那用起来就很不方便了。 所以下面分享一个脚本来实现批量key的迁移&#xff0c;主要使用的命令为dump和restore 脚本如下&#xff1a; #!/bin/bash redis-cli -h host1 -p 63…

第19章_体系结构

文章目录 1. 逻辑架构剖析1.1 服务器处理客户端请求1.2 Connectors1.3 第1层&#xff1a;连接层1.4 第2层&#xff1a;服务层1.4.1 SQL Interface: SQL接口1.4.2 Parser: 解析器1.4.3 Optimizer: 查询优化器1.4.4 Caches & Buffers&#xff1a; 查询缓存组件 1.5 第3层&…

详细创建Prism架构wpf项目

方案一&#xff1a; 1.创建一个普通wpf项目 2、安装NuGet包&#xff1a;Prism.DryIoc 3、App.xaml.cs中: 将原本的父类Application改为&#xff1a;PrismApplication&#xff0c;并且实现抽象类 CreateShell方法中写上&#xff1a;”return Container.Resolve<MainWindow>…

YOLO目标检测——交通标志识别数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;交通标志识别数据集在自动驾驶、交通安全监控、智能交通系统、驾驶员辅助系统和城市规划等领域都有广泛应用的潜力数据集说明&#xff1a;交通标志识别数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含有交通标识6类…

电源模块的测试方法都有哪些?如何用ATECLOUD进行测试?

电源模块的测试方法主要包括以下步骤&#xff1a; 连接设备&#xff1a;通过LAN通讯总线、测试夹具以及其它线缆对测试所需的设备和需要测试的电源模块进行连接&#xff0c;同时接入纳米box进入登录ATECLOUD云测试平台。 创建测试项目&#xff1a;根据所以的设备仪器搭建所需…