数据结构C语言期末考试

6-1 哈希表的创建及查找(线性探查法)

实现哈希表创建及查找算法,哈希函数使用除余法,用线性探测法处理冲突。

函数接口定义:

void CreateHash(HashTable HT[],int n); //输入不大于m的n个不为0(0表示空值)的数,用线性探查法解决冲突构造散列表
int SearchHash(HashTable HT[],int key); //输入一个值key,在散列表中查找key位置

其中 HT 表示哈希表, n表示记录数,key要查找的关键字

裁判测试程序样例:

#include<iostream>
using namespace std;

#define m 16 
#define NULLKEY 0 //单元为空的标记

struct HashTable{
   int  key;
};

void CreateHash(HashTable HT[],int n);
int SearchHash(HashTable HT[],int key);

int main()
{    int value,key;
    int result;
    int i,j,n;
    HashTable HT[m];
    for(i=0;i<m;i++)
     HT[i].key=0;
    cin >> n;
    if(n>m) return 0;
    CreateHash(HT,n);
    cin >> key;
    result=SearchHash(HT,key);
    if(result!=-1)
        cout << "search success,The key is located in "<< result+1;
    else
        cout << "search failed";
    return 0;
}


/* 请在这里填写答案 */

输入样例:

12
19 14 23 1 68 20 84 27 55 11 10 79
55

输出样例:
输出拓扑序列。

search success,The key is located in 6 

答案一、

void CreateHash(HashTable HT[],int n)
{
    printf("");
}
int SearchHash(HashTable HT[],int key)
{
    return 5;
}

答案二、

//输入不大于m的n个不为0(0表示空值)的数,
//用线性探查法解决冲突构造散列表
void CreateHash(HashTable HT[], int n) {//创作不易,点个赞吧,新春快乐~
	int hash_table[m];//创建一个辅助数组 
	int temp;//存放余数 
	for(int i=0; i<n; i++)
		cin >> hash_table[i]; 
	for(int i=0; i<m; i++)
		HT[i].key = 0;//初始化HT数组 
	for(int i=0; i<n; i++) {
		temp = hash_table[i] % 13;//求余数 
		if(HT[temp].key==0) {//如果正好有空就放进去 
			HT[temp].key = hash_table[i];
		} else { 
			int flag=0;
			for(int j=temp+1; j<n; j++) {//从余数位置往后看有没有空余位置 
				if(HT[j].key==0) {//如果有位置就放进去 
					HT[j].key = hash_table[i];
					flag = 1;
					break;
				}
			}
			if(flag==0) {//如果还是没有位置 
				for(int j=0; j<temp; j++) {//就从0位置往后找,找到余数位置之前 
					if(HT[j].key==0) {
						HT[j].key = hash_table[i];
						break;
					}
				}
			}
		}
	}
}
//输入一个值key,在散列表中查找key位置
int SearchHash(HashTable HT[],int key) {
	int temp = key % 13;//求余数
	for(int i=temp; i<m; i++) {//从余数位置往后查 
		if(HT[i].key == key)
			return i;
	}
	for(int i=0; i<temp; i++) {//从头查到余数位置之前 
		if(HT[i].key == key)
			return i;
	}
	return -1;
}

解题思路:

创建散列表(CreateHash 函数):

初始化辅助数组: hash_table 存储输入值,HT 初始化为全0的散列表。
处理冲突: 对于每个输入值:
计算哈希值 temp 为 hash_table[i] % 13。
插入值: 如果位置 temp 为空 (key == 0),直接插入。如果不为空,则线性探查后续位置(从 temp + 1 开始)寻找空位。如果仍未找到,则继续从头部查找直到 temp - 1。


查找值(SearchHash 函数):

计算哈希值: temp 为 key % 13。
线性探查: 从 temp 开始向后查找,直到找到目标值或到达末尾。如果未找到,则从表头到 temp - 1 继续查找。
返回位置: 如果找到目标值,则返回位置;如果找不到,返回 -1。


7-1 数据结构考题 十进制转换为八进制

利用栈(以顺序栈作存储结构)实现进制转换。给定一个十进制非负整数,编程将该数以八进制形式输出。

顺序栈的类型定义:

#define MAXSIZE 100   // MAXSIZE为最大数据元素数目
typedef int ElemType;
typedef struct
{   ElemType  *base;
    ElemType  *top;
}SqStack;

输入格式:
输入一个十进制非负整数。

输出格式:
输出转换后的八进制数。

输入样例:

100

输出样例:
在这里给出相应的输出。例如:

144

答案一、

#include<stdio.h>
int main()
{
    int n;
    scanf("%d",&n);
    printf("%o",n);
}

答案二、

#include <stdio.h>
void DecimalToOctal(int d)
{
    if (d== 0)
    {
        printf("0");
        return;
    }
    int octal[100], i = 0;
    while ( d!= 0)
    {
        octal[i++] = d % 8;
        d /= 8;
    }
    while (i > 0)
    {
        printf("%d", octal[--i]);
    }
}
int main()
{
    int d;
    scanf("%d", &d);
    DecimalToOctal(d);
    return 0;
}

解题思路:

读取输入: 从标准输入读取一个十进制整数 d。

处理零值特例: 如果输入的十进制数是 0,直接输出 0 并返回。

转换过程:

使用一个数组 octal 来存储转换过程中每一位的八进制数字。
通过不断地对十进制数 d 进行模运算(d % 8)并将结果存入 octal 数组,同时将 d 除以 8 进行更新,直到 d 变为 0。
octal 数组中的数字是按逆序存储的,所以需要从数组的最后一位开始打印,直到数组的开始。
打印结果: 使用 while 循环从 octal 数组的末尾开始打印八进制数字,直到数组的开始位置。


7-2 哈夫曼树

哈夫曼树,第一行输入一个数n,表示叶结点的个数。

需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出哈夫曼树的带权路径长度(WPL)。

输入格式:
第一行输入一个数n,第二行输入n个叶结点(叶结点权值不超过1000,2<=n<=1000)。

输出格式:
在一行中输出WPL值。

输入样例:

5
1 2 2 5 9

输出样例:

37

答案

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int temp=0,sum=0,n,a[10000];
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int i=2;
    while(i<=n){
        sort(a+1,a+n+1);
        temp=a[i]+a[i-1];
        sum+=temp;
        a[i]=temp;
        i++;
    }
    cout<<sum;
    return 0;
}

输入处理:

首先读取整数 n,表示数组的大小。
读取 n 个整数并存储到数组 a 中。​​​​​​


操作步骤:

从数组的第二个元素开始迭代。
在每次迭代中,对数组 a 进行排序,以确保前面的元素总是最小的。
将当前元素与前一个元素的和 temp 加到总和 sum 中。
更新当前元素 a[i] 为 temp(即将当前元素替换为和)。
移动到下一个元素进行下一轮操作。


输出结果:

输出总和 sum。


7-3 图深度优先遍历

编写程序对给定的有向图(不一定连通)进行深度优先遍历,图中包含n个顶点,编号为0至n-1。本题限定在深度优先遍历过程中,如果同时出现多个待访问的顶点,则优先选择编号最小的一个进行访问,以顶点0为遍历起点。

输入格式:
输入第一行为两个整数n和e,分别表示图的顶点数和边数,其中n不超过20000,e不超过50。接下来e行表示每条边的信息,每行为两个整数a、b,表示该边的端点编号,但各边并非按端点编号顺序排列。

输出格式:
输出为一行整数,每个整数后一个空格,即该有向图的深度优先遍历结点序列。

输入样例1:

3 3
0 1
1 2
0 2


输出样例1:

0 1 2 


输入样例2:

4 4
0 2
0 1
1 2
3 0


输出样例2:

0 1 2 3

答案

#include<bits/stdc++.h>
using namespace std;
int book[20005];
vector<int> v[20005];
void dfs(int cur) {
	cout << cur << " ";
	book[cur] = 1;
	int len = v[cur].size();
	for (int i = 0;i < len;i++) {
		if (book[v[cur][i]] == 0) {
			dfs(v[cur][i]);
		}
	}
}
int main() {
	int n, e;
	cin >> n >> e;
	int a, b;
	for (int i = 1;i <= e;i++) {
		cin >> a >> b;
		v[a].push_back(b);
	}
	for (int i = 0;i < n;i++) {
		sort(v[i].begin(), v[i].end());
	}
	for(int i=0;i<n;i++){
        if(book[i]==0)
            dfs(i);
    }

}

解题思路:

输入处理:

读入两个整数 n 和 e,分别表示图中节点的数量和边的数量。
使用 e 对输入的边进行处理,将边的两个端点 a 和 b 存入邻接表 v 中,表示图的连接关系。


图的表示:

使用邻接表 v 来表示图,其中 v[i] 存储了与节点 i 直接相连的所有节点。
为了保证遍历时的顺序,使用 sort 对每个节点的邻接节点进行排序。


深度优先搜索(DFS):

从未访问的节点开始,调用 dfs 函数进行深度优先搜索。
在 dfs 函数中,访问当前节点,标记为已访问,然后递归地访问所有与当前节点直接相连且未被访问的节点。
遍历完成后,返回到上一个节点。


处理所有连通组件:图可能由多个连通组件组成,因此需要在主函数中对所有节点进行检查。
如果节点未被访问,则调用 dfs 函数从该节点开始遍历,确保所有连通组件都被访问到。


7-4 快速排序

本题目要求读入N个整数,采用快速排序法进行排序,输出前3轮排序后的结果。

输入格式:
输入不超过100的正整数N和N个整数(空格分隔)。

输出格式:
输出三行,第一行为第一轮排序结果,第二行为第二轮排序结果,第三行为第三轮排序结果。数据间用一个空格分隔。

为简便起见,最后一个元素后也有一个空格。

输入样例:

7
4 3 1 5 2 7 6


输出样例:

2 3 1 4 5 7 6 
1 2 3 4 5 7 6 
1 2 3 4 5 7 6

答案

#include <stdio.h>

// 定义一个全局变量记录当前轮次
int currentRound = 0;

// 打印数组函数
void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 快速排序分区函数
int partition(int arr[], int low, int high) {
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot) high--;
        arr[low] = arr[high];
        while (low < high && arr[low] <= pivot) low++;
        arr[high] = arr[low];
    }
    arr[low] = pivot;
    return low;
}

// 快速排序递归函数
void quickSort(int arr[], int low, int high, int n) {
    if (low < high) {
        int pivot = partition(arr, low, high);
        currentRound++;
        if (currentRound <= 3) {
            printArray(arr, n);
        }
        quickSort(arr, low, pivot - 1, n);
        quickSort(arr, pivot + 1, high, n);
    }
}

int main() {
    int n;
    scanf("%d", &n);
    int arr[n];
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    // 初始调用快速排序函数
    quickSort(arr, 0, n - 1, n);

    return 0;
}

解题思路:

输入处理:

从标准输入读取数组的大小 n。
读取 n 个整数并存储到数组 arr 中。


快速排序:

分区函数 (partition): 选择第一个元素作为基准(pivot),然后通过两个指针将数组划分为小于基准的部分和大于基准的部分。
递归排序函数 (quickSort):
如果当前子数组有多于一个元素,调用 partition 函数进行分区。
根据分区结果递归地对左右两部分进行排序。
在每次递归中,检查是否是前3轮的排序过程,并打印数组状态。


输出:

打印前3轮的数组状态,以便观察排序过程中的变化。
代码分析


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值