考研数据结构程序题常见代码【C语言实现】

考研院校要求C语言实现数据结构,可前期做数据结构都是用Java实现,因此对于C不那么熟悉,花了一些时间重新捡起来C的语法,程序题通常不会考太过复杂的算法,现整理如下👇

1. 链表

1.1 结构体实现链表样例

#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
	int num;
	struct Node* next;
} Node;
//创建一个数值为i的节点并插入在节点p后边
void insert(Node* p, int i) {
	//指针指向Node这么大的空间
	Node* temp = malloc(sizeof(Node));
	temp->next = NULL;
	temp->num = i;
	p->next = temp;
}
int main() {
	Node* node = malloc(sizeof(Node));
	node->num = 1;
	node->next = NULL;
	insert(node, 10);
	while (node != NULL) {
		printf("%d ", node->num);
		node = node->next;
	}
}

1.2 头插尾插与反转

#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
	int val;
	struct Node* next;
} Node;
//头插法
void InsertNode(Node* head, Node* p);
//尾插法
void InsertNodeBehind(Node* head, Node* p);
//链表反转 (递归实现)
void reverseList(Node* head, Node* temp);
//头插法实现链表反转
void reverseList2(Node* head);

int main() {
	Node* head = malloc(sizeof(Node));
	head->val = -1;
	head->next = NULL; //初始化很重要
	for (int i = 1; i <= 10; i++) {
		Node* temp = malloc(sizeof(Node));
		temp->val = i;
		temp->next = NULL;
		// 尾插
		InsertNodeBehind(head, temp);
	}
	// 头插法实现反转
	reverseList2(head);
	head = head->next;
	while (head != NULL) {
		printf("%d ", head->val);
		head = head->next;
	}
}

void InsertNode(Node* head, Node* p) {
	p->next = head->next;
	head->next = p;
}

void InsertNodeBehind(Node* head, Node* p) {
	Node* temp = head;
	while (temp->next != NULL) {
		temp = temp->next;
	}
	temp->next = p;
}

void reverseList(Node* head, Node* temp) {
	if (temp->next == NULL) {
		head->next = temp;
		return;
	} else if (temp->next != NULL) {
		reverseList(head, temp->next);
		temp->next->next = temp;
		temp->next = NULL;
	}
}

void reverseList2(Node* head) {
	if (head->next == NULL || head->next->next == NULL) {
		return;
	}
	Node* p = head->next->next;
	head->next->next = NULL;
	Node* p1;
	while (p) {
		p1 = p->next;
		p->next = head->next;
		head->next = p;
		p = p1;
	}
}

2. 树

image-20230320095228591

2.1 树的遍历

2.1.1 前中后序遍历

#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
	int val;
	struct Node* left;
	struct Node* right;
} Node;
void initial();
// 前序遍历
void prePrint(Node* root);
// 中序遍历
void midPrint(Node* root);
// 后序遍历
void lastPrint(Node* root);
// 树的高度
int getHeight(Node* root);
Node *root, *node1, *node2, *node3, *node4, *node5, *node6, *node7;
int main() {
	// 初始化很重要
	initial();
	printf("前序遍历序列为:");
	prePrint(root);
	printf("\n中序遍历序列为:");
	midPrint(root);
	printf("\n后序遍历序列为:");
	lastPrint(root);
	printf("\n树的高度是:%d", getHeight(root));
}
//树的高度
int getHeight(Node* root) {
	if (root == NULL) {
		return 0;
	}
	int a = getHeight(root->left) + 1;
	int b = getHeight(root->right) + 1;
	return a > b ? a : b;
}
//前序遍历
void prePrint(Node* root) {
	printf("%d ", root->val);
	if (root->left != NULL) {
		prePrint(root->left);
	}
	if (root->right != NULL) {
		prePrint(root->right);
	}
}
//中序遍历
void midPrint(Node* root) {
	if (root->left != NULL) {
		midPrint(root->left);
	}
	printf("%d ", root->val);
	if (root->right != NULL) {
		midPrint(root->right);
	}
}
//后序遍历
void lastPrint(Node* root) {
	if (root->left != NULL) {
		lastPrint(root->left);
	}
	if (root->right != NULL) {
		lastPrint(root->right);
	}
	printf("%d ", root->val);
}
void initial() {
	root = malloc(sizeof(Node));
	node1 = malloc(sizeof(Node));
	node2 = malloc(sizeof(Node));
	node3 = malloc(sizeof(Node));
	node4 = malloc(sizeof(Node));
	node5 = malloc(sizeof(Node));
	node6 = malloc(sizeof(Node));
	node7 = malloc(sizeof(Node));

	root->val = 0;
	node1->val = 1;
	node2->val = 2;
	node3->val = 3;
	node4->val = 4;
	node5->val = 5;
	node6->val = 6;
	node7->val = 7;

	root->left = node1;
	root->right = node2;
	node1->left = node3;
	node1->right = node4;
	node2->left = node5;
	node2->right = node6;
	node3->left = node7;
	node3->right = NULL;
	node4->left = NULL;
	node4->right = NULL;
	node5->left = NULL;
	node5->right = NULL;
	node6->left = NULL;
	node6->right = NULL;
	node7->left = NULL;
	node7->right = NULL;
}

2.1.2 层次遍历

层次遍历需要使用队列queue,而C语言中没有现成的队列可以调用,因此此处实现使用了少许C++的代码,如结构体中的构造函数,分配空间使用new语法【malloc仅仅分配空间而不会调用构造函数,C++中需要调用构造函数才能为结构体(或对象)申请内存空间,因此只能用new而不能用malloc

若院校要求C语言实现,则写试卷时用注释交代一下队列的情况、内置的方法情况即可拿来使用

#include<stdio.h>
#include<queue>
using namespace std;
typedef struct Node {
	int val;
	Node* left;
	Node* right;
	Node(int val, Node* left, Node* right) {
		this->val = val;
		this->left = left;
		this->right = right;
	}
} Node;
void initial();
void rowPrint(Node *root);
Node *root, *node1, *node2, *node3, *node4, *node5, *node6, *node7;
queue<Node*> q;
int main() {
	initial();
	printf("层序遍历次序为:");
	rowPrint(root);
}
//层序遍历
void rowPrint(Node* root) {
	q.push(root);
	while (!q.empty()) {
		int n = q.size();
		for (int i = 0; i < n; i++) {
			Node *temp = q.front();
			if (temp->left != NULL) {
				q.push(temp->left);
			}
			if (temp->right != NULL) {
				q.push(temp->right);
			}
			printf("%d ", temp->val);
			q.pop();
		}
	}
}
void initial() {
	// 需要保证传入参数时对象已经构建,所以对执行顺序有要求
	// 此处为了节省篇幅而采用C++的构造函数,C语言只能按照??2.1.1的initial函数中的方法初始化
	node4 = new Node(4, NULL, NULL);
	node5 = new Node(5, NULL, NULL);
	node6 = new Node(6, NULL, NULL);
	node7 = new Node(7, NULL, NULL);
	node3 = new Node(3, node7, NULL);
	node1 = new Node(1, node3, node4);
	node2 = new Node(2, node5, node6);
	root = new Node(0, node1, node2);
}

2.2 二叉排序树

image-20230320144029448
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
	int val;
	struct Node* left;
	struct Node* right;
} Node;
Node *root, *node1, *node2, *node3, *node5, *node6, *node7;
// 中序遍历
void midPrint(Node* root);
// 往二叉排序树插入结点
void insertNode(Node* root, Node* temp);
// 初始化
void initial();
// 递归查找某个值对应的节点
Node* searchByVal(Node* root, int val);
// 非递归查找
Node* searchByVal2(Node* root, int val);
int main() {
	initial();//初始化
	printf("中序输出二叉排序树:");
	midPrint(root);
	Node* temp = searchByVal(root, 5);
	printf("\n%c", temp == NULL ? 'F' : 'T');
}

Node* searchByVal(Node* root, int val) {
	if (root == NULL) {
		return NULL;
	} else if (root->val == val) {
		return root;
	} else if (root->val < val) {
		return searchByVal(root->right, val);
	} else {
		return searchByVal(root->left, val);
	}
}

Node* searchByVal2(Node* root, int val) {
	while (root != NULL) {
		if (root->val == val) {
			return root;
		} else if (root->val < val) {
			root = root->right;
		} else {
			root = root->left;
		}
	}
	return NULL;
}

void insertNode(Node* root, Node* temp) {
	if (temp->val < root->val) {
		if (root->left != NULL) {
			insertNode(root->left, temp);
		} else {
			root->left = temp;
		}
	} else {
		if (root->right != NULL) {
			insertNode(root->right, temp);
		} else {
			root->right = temp;
		}
	}
}

void midPrint(Node* root) {
	if (root->left != NULL) {
		midPrint(root->left);
	}
	printf("%d ", root->val);
	if (root->right != NULL) {
		midPrint(root->right);
	}
}

void initial() {
	root = malloc(sizeof(Node));
	node1 = malloc(sizeof(Node));
	node2 = malloc(sizeof(Node));
	node3 = malloc(sizeof(Node));
	node5 = malloc(sizeof(Node));
	node6 = malloc(sizeof(Node));
	node7 = malloc(sizeof(Node));

	root->val = 4;
	node1->val = 1;
	node2->val = 2;
	node3->val = 3;
	node5->val = 5;
	node6->val = 6;
	node7->val = 7;

	root->left = NULL;
	root->right = NULL;
	node1->left = NULL;
	node1->right = NULL;
	node2->left = NULL;
	node2->right = NULL;
	node3->left = NULL;
	node3->right = NULL;
	node5->left = NULL;
	node5->right = NULL;
	node6->left = NULL;
	node6->right = NULL;
	node7->left = NULL;
	node7->right = NULL;

	insertNode(root, node2);
	insertNode(root, node6);
	insertNode(root, node1);
	insertNode(root, node3);
	insertNode(root, node5);
	insertNode(root, node7);
}

2.3 顺序存储二叉树与链式二叉树转换

此处用到queue,同样使用到了部分C++语法,若怕搞不清哪些是C的语法,哪些是C++语法,可以在执行文件时候保存为.c后缀的文件再编译运行【C++后缀是.cpp】,此时不属于C的语法就会报错

#include<stdio.h>
#include<stdlib.h>
#include<queue>
using namespace std;
typedef struct Node {
	int val;
	int in; //在数组中哪个下标
	Node* left;
	Node* right;
	Node(int val, int in, Node* left, Node* right) {
		this->val = val;
		this->in = in;
		this->left = left;
		this->right = right;
	}
} Node;

queue<Node*> list;
// 返回当前节点右孩子
int rChild (int index, int n, int arr[]);
// 返回当前节点左孩子
int lChild (int index, int n, int arr[]);
// 顺序二叉树的先序遍历
void prePrint(int index, int arr[], int n);
// 链式二叉树先序遍历
void prePrint2(Node* root);
// 顺序二叉树的广度遍历直接for遍历数组即可,省略实现
void BFS(int, int[], int);
// 创建一个节点
Node* indexToNode(int index, int arr[]);
// 将顺序存储二叉树转换为链式存储二叉树,返回根节点
Node* arrToList(int arr[], int n);

int main() {
	// 顺序存储时下标0不存储结点,从 1 开始存储
	// 此时若当前结点的下标为index,则其左孩子下标为 2*index,右孩子下标为 2*index + 1
	int arr[] = {-1, 52, 30, 68, 20, 50, 60, 70};
	// 得到数组长度
	int n = sizeof(arr) / sizeof(arr[0]);
	printf("顺序存储的前序遍历:");
	prePrint(1, arr, n);
	printf("\n\n链式存储的前序遍历:");
	Node* root = arrToList(arr, n);
	prePrint2(root);
}

Node* arrToList(int arr[], int n) {
	Node* root = indexToNode(1, arr);
	list.push(root);
	while (!list.empty()) {
		Node* temp = list.front();
		list.pop();
		// 当前节点对应左节点下标
		int left = lChild(temp->in, n, arr);
		if (left != -1) {
			Node* lNode = indexToNode(left, arr);
			temp->left = lNode;
			list.push(lNode);
		}
		// 当前节点对应右节点下标
		int right = rChild(temp->in, n, arr);
		if (right != -1) {
			Node* rNode = indexToNode(right, arr);
			temp->right = rNode;
			list.push(rNode);
		}
	}
	return root;
}

Node* indexToNode(int index, int arr[]) {
	Node* root = new Node(arr[index], index, NULL, NULL);
	return root;
}

void prePrint(int index, int arr[], int n) {
	if (arr[index] != -1) {
		printf("%d ", arr[index]);
	}
	// 根据index指向的结点左孩子的下标
	int left = lChild(index, n, arr);
	if (left != -1) {
		prePrint(left, arr, n);
	}
	// 根据index指向的结点右孩子的下标
	int right = rChild(index, n, arr);
	if (right != -1) {
		prePrint(right, arr, n);
	}
}

int lChild (int index, int n, int arr[]) {
	int lIndex = index * 2;
	if (lIndex < n && arr[lIndex] != -1) {
		return lIndex;
	} else {
		return -1;
	}
}

int rChild (int index, int n, int arr[]) {
	int rIndex = (index * 2) + 1;
	if (rIndex < n && arr[rIndex] != -1) {
		return rIndex;
	} else {
		return -1;
	}
}

//链式前序遍历
void prePrint2(Node* root) {
	if (root == NULL) {
		return;
	}
	printf("%d ", root->val);
	prePrint2(root->left);
	prePrint2(root->right);
}

3. 排序

快速排序与归并排序

#include<stdio.h>
#include<stdlib.h>
// 快速排序
void QuickSort(int [], int, int);
// 快速排序中每次确定的索引位置
int returnIndex(int [], int, int);

// 归并排序
void MergeSort(int [], int, int, int);
// 将一分为二排好序的数组进行最终排序
void Merge(int [], int, int, int);

int main() {
	int arr[] = {5, 7, 4, 8, 9, 2, 1, 3, 6};
	// 得到数组长度
	int n = sizeof(arr) / sizeof(int);
	printf("排序前的数组为:");
	for (int i = 0; i < n; i++) {
		printf("%d ", arr[i]);
	}
	// QuickSort(arr,0,n-1);
	MergeSort(arr, 0, n - 1, n);
	printf("\n\n排序后的数组为:");
	for (int i = 0; i < n; i++) {
		printf("%d ", arr[i]);
	}
}

void MergeSort(int arr[], int left, int right, int length) {
	if (left < right) {
		int mid = (left + right) / 2;
		MergeSort(arr, left, mid, length);
		MergeSort(arr, mid + 1, right, length);
		Merge(arr, left, right, length);
	}
}
void Merge(int arr[], int left, int right, int length) {
	// 创建一个数组,大小与arr一致
	// C语言规定数组大小时不允许传入变量,因此此处用指针“曲线救国”
	int* temp = malloc(length * sizeof(int));
	int mid = (left + right) / 2;
	for (int i = left; i <= right; i++) {
		temp[i] = arr[i];
	}
	int index = left, i = left, j = mid + 1;
	while (i <= mid && j <= right) {
		if (temp[i] > temp[j]) {
			arr[index++] = temp[j++];
		} else {
			arr[index++] = temp[i++];
		}
	}
	while (i <= mid) {
		arr[index++] = temp[i++];
	}
	while (j <= right) {
		arr[index++] = temp[j++];
	}
}

void QuickSort(int arr[], int left, int right) {
	if (left < right) {
		int mid = returnIndex(arr, left, right);
		QuickSort(arr, left, mid - 1);
		QuickSort(arr, mid + 1, right);
	}
}
int returnIndex(int arr[], int left, int right) {
	int temp = arr[left];
	while (left < right) {
		while (left < right && arr[right] >= temp) {
			right--;
		}
		arr[left] = arr[right];
		while (left < right && arr[left] <= temp) {
			left++;
		}
		arr[right] = arr[left];
	}
	arr[left] = temp;
	return left;
}

4. 查找

二分查找

#include<stdio.h>
// 递归方式的二分查找
int HalfSearch(int left, int right, int arr[], int target);
// 非递归方式的二分查找
int HalfSearch2(int left, int right, int arr[], int target);

int main() {
	int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
	int n = sizeof(arr) / sizeof(int);
	int index = HalfSearch2(0, n - 1, arr, 4);
	printf("目标位置索引为:%d", index);
}

int HalfSearch(int left, int right, int arr[], int target) {
	if (left > right) {
		return -1;
	}
	// 中间索引
	int midIndex = (left + right) / 2;
	// 中间值
	int mid = arr[midIndex];
	if (target == mid) {
		return midIndex;
	} else if (target < mid) {
		return HalfSearch(left, midIndex - 1, arr, target);
	} else {
		return HalfSearch(midIndex + 1, right, arr, target);
	}
}

int HalfSearch2(int left, int right, int arr[], int target) {
	int index = -1;
	while (left <= right) {
		// 中间索引
		index = (left + right) / 2;
		// 中间值
		int mid = arr[(left + right) / 2];
		if (target == mid) {
			return index;
		} else if (target < mid) {
			right = index - 1;
		} else {
			left = index + 1;
		}
	}
	return index;
}

5. 图

邻接表代码较多,估计不好出考试题

邻接矩阵

image-20230320154105749
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#define MAX 10
using namespace std;
typedef struct Graph {
	// 顶点表
	int Vex[MAX];
	// 邻接矩阵
	int Edge[MAX][MAX];
	// 顶点数和弧数
	int vexNum, arcNum;
	// 节点是否访问,初始全为 false,即未被访问
	bool Visited[MAX] = {false};
	Graph() {
		// 初始顶点数为 0
		vexNum = 0;
		// 初始边数为 0
		arcNum = 0;
	}
} Graph;
Graph *g;
queue<int> q;
// 初始化顶点表,矩阵等信息
void initial();
// 无向图插入边
void insertEdge(int, int, int);
// 广度优先遍历
void DFS(int);
// 深度优先遍历
void BFS(int);
int main() {
	initial();
	printf("深度优先遍历:");
	// 从结点 1 出发
	DFS(1);
	initial();
	printf("\n广度优先遍历:");
	BFS(1);
}

void BFS(int index) {
	q.push(index);
	g->Visited[index] = true;
	while (!q.empty()) {
		int n = q.size();
		for (int i = 0; i < n; i++) {
			int j = q.front();
			q.pop();
			printf("%d ", g->Vex[j]);
			for (int x = 0; x < MAX; x++) {
				if (g->Edge[j][x] != 0 && g->Visited[x] == false) {
					q.push(g->Vex[x]);
					// 放进队列就相当于访问过
					g->Visited[x] = true;
				}
			}
		}
	}
}

void DFS(int index) {
	printf("%d ", g->Vex[index]);
	g->Visited[index] = true;
	for (int i = 0; i < MAX; i++) {
		if (g->Edge[index][i] != 0 && g->Visited[i] == false) {
			DFS(i);
		}
	}
}

void insertEdge(int Vex1, int Vex2, int Power) {
	// 无向图添两边
	g->Edge[Vex1][Vex2] = Power;
	g->Edge[Vex2][Vex1] = Power;
}

void initial() {
	g = new Graph;
	for (int i = 0; i < MAX; i++) {
		for (int j = 0; j < MAX; j++) {
			g->Edge[i][j] = 0; //此时顶点i与j之间没有通路
		}
		g->Vex[i] = i; //0~9号顶点
	}
	// 顶点1与顶点2之间有通路
	insertEdge(1, 2, 1);
	insertEdge(1, 4, 1);
	insertEdge(2, 3, 1);
	insertEdge(3, 5, 1);
	insertEdge(5, 2, 1);
	insertEdge(4, 3, 1);
}

总结

这些整理希望能够帮助到你们,祝你们考研成功!

  • 11
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
数据结构18001. 算法的计算量的大小称为计算的( )。【北京邮电大学2000 二、3 (20/8分)】 A.效率 B. 复杂性 C. 现实性 D. 难度 2. 算法的时间复杂度取决于( )【中科院计算所 1998 二、1 (2分)】 A.问的规模 B. 待处理数据的初态 C. A和B 3.计算机算法指的是(1),它必须具备(2) 这三个特性。 (1) A.计算方法 B. 排序方法 C. 解决问的步骤序列 D. 调度方法 (2) A.可执行性、可移植性、可扩充性 B. 可执行性、确定性、有穷性 C. 确定性、有穷性、稳定性 D. 易读性、稳定性、安全性 【南京理工大学 1999 一、1(2分) 【武汉交通科技大学 1996 一、1( 4分)】 4.一个算法应该是( )。【中山大学 1998 二、1(2分)】 A.程序 B.问求解步骤的描述 C.要满足五个基本特性 D.A和C. 5. 下面关于算法说法错误的是( )【南京理工大学 2000 一、1(1.5分)】 A.算法最终必须由计算机程序实现 B.为解决某问的算法同为该问编写的程序含义是相同的 C. 算法的可行性是指指令不能有二义性 D. 以上几个都是错误的 6. 下面说法错误的是( )【南京理工大学 2000 一、2 (1.5分)】 (1)算法原地工作的含义是指不需要任何额外的辅助空间 (2)在相同的规模n下,复杂度O(n)的算法在时间上总是优于复杂度O(2n)的算法 (3)所谓时间复杂度是指最坏情况下,估算算法执行时间的一个上界 (4)同一个算法,实现语言的级别越高,执行效率就越低 A.(1) B.(1),(2) C.(1),(4) D.(3) 7.从逻辑上可以把数据结构分为( )两大类。【武汉交通科技大学 1996 一 、4(2分)】 A.动态结构、静态结构 B.顺序结构、链式结构 C.线性结构、非线性结构 D.初等结构、构造型结构
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值