下面代码自己上完课写着玩的,除了克鲁斯卡尔那里完全ai,其他基本上都是自己写的,具体请参考书本,同时也欢迎各位大佬来纠错
线性表
//线性表--顺序存储结构
#include<iostream>
using namespace std;
template<typename T> //typename可以用class代替
struct sequentaillist {
T* element;
int size; //大小
int capital; //容量
};
template<typename T>
void initlist(sequentaillist<T>* List,int capital) { //初始化的过程其实就是分别初始化list三个变量
List->element = new T[capital]; //动态分配内存
List->size = 0;
List->capital = capital;
}
template<typename T>
void destroylist(sequentaillist<T>* list) { //销毁线性表
delete[] list->element; //释放内存
}
template<typename T>
bool isempty(sequentaillist<T> list) {
return list->size == 0; //判断是否为空表
}
template<typename T>
int getsize(sequentaillist<T> list) { //返回表长
return list.size;
}
template<typename T>
void clearlist(sequentaillist<T>* list) { //清空表长,就像未使用过一样
if (list == nullptr) return;
delete[] list->element;
list->element = nullptr;
list->size = 0;
list->capital = 0;
}
template<typename T>
T getvalue(sequentaillist<T> list , int i) { //获取表中第i个元素的值
if (list.element == nullptr) return nullptr;
if (i<0 || i>list.size) {
cout << "下标越界" << endl;
return nullptr;
}
return list.element[i];
}
template<typename T>
int findelement(sequentaillist<T> list, int value) { //查找元素
if (list.element == nullptr) return -1;
for (int i = 0; i < list.size; i++) {
if (list.element[i] == value) {
return i;
}
}
return -1; //没找到
}
template<typename T>
void insert(sequentaillist<T>* list, int i , T value) { //在第i个位置插入元素value
if (list == nullptr) return;
if (i<0 || i>list->size) {
cout << "下标越界" << endl;
return;
}
if (list->size == list->capital) { //满了,扩容
T* newelement = new T[list->capital * 2]; //扩容两倍
for (int i = 0; i < list->size; i++) {
newelement[i] = list->element[i];
}
delete[] list->element;
list->element = newelement;
list->capital = list->capital * 2;
}
for (int j = list->size; j > i; j--) {
list->element[j + 1] = list->element[i];
}
list->element[i] = value;
list->size++;
}
template<typename T>
void deleteelement(sequentaillist<T>* list, int i) { //删除第i个元素
if (list == nullptr) return;
if (i<0 || i>list->size) {
cout << "下标越界" << endl;
return;
}
for (int j = i; j < list->size - 1; j++) {
list->element[j] = list->element[j + 1];
}
list->size--;
}
template<typename T>
void remove(sequentaillist<T>* list, int value) { //删除表中的所有value
if (list == nullptr) return;
for (int i = 0; i < list->size; i++) {
if (list->element[i] == value) {
deleteelement(list, i);
i--; //删除位置后因为所有元素都要向前一位,覆盖了原本的i号位置,所以i号位置重新比较一遍
}
}
}
template<typename T>
void setvalue(sequentaillist<T>* list, int i, int value) { //设置第i个元素的值
if (list == nullptr) return;
if (i<0 || i>list->size) {
cout << "下标越界" << endl;
return;
}
list->element[i] = value;
}
int main() {
// 初始化线性表
sequentaillist<int> list;
initlist(&list, 5); // 初始容量为5
cout << "初始化线性表,容量为5" << endl;
// 插入元素
insert(&list, 0, 10);
insert(&list, 1, 20);
insert(&list, 2, 30);
cout << "插入元素后,线性表内容为:";
for (int i = 0; i < list.size; i++) {
cout << list.element[i] << " ";
}
cout << endl;
// 查找元素
int value = 20;
int index = findelement(list, value);
if (index != -1) {
cout << "查找元素" << value << ",位置为:" << index << endl;
}
else {
cout << "查找元素" << value << ",未找到" << endl;
}
// 删除元素
deleteelement(&list, 1);
cout << "删除第1个元素后,线性表内容为:";
for (int i = 0; i < list.size; i++) {
cout << list.element[i] << " ";
}
cout << endl;
// 删除所有指定值的元素
remove(&list, 30);
cout << "删除所有值为30的元素后,线性表内容为:";
for (int i = 0; i < list.size; i++) {
cout << list.element[i] << " ";
}
cout << endl;
// 设置元素值
setvalue(&list, 0, 100);
cout << "设置第0个元素值为100后,线性表内容为:";
for (int i = 0; i < list.size; i++) {
cout << list.element[i] << " ";
}
cout << endl;
// 清空线性表
clearlist(&list);
cout << "清空线性表后,线性表大小为:" << getsize(list) << endl;
// 销毁线性表
destroylist(&list);
cout << "销毁线性表" << endl;
return 0;
}
//线性表--链式存储结构
#include <iostream>
using namespace std;
// 定义链表节点模板结构
template <typename T>
struct Node {
T data; // 数据域
Node<T>* next; // 指向下一个节点的指针
};
// 定义链表模板类
template <typename T>
class LinkedList {
private:
Node<T>* head; // 头节点指针
public:
// 构造函数
LinkedList() : head(nullptr) {}
// 析构函数
~LinkedList() {
destroy(head); // 销毁链表
}
// 初始化链表
void init() {
head = new Node<T>; // 创建头节点
head->next = nullptr;
}
// 判断链表是否为空
bool isempty() const {
return head->next == nullptr;
}
// 获取链表长度
int getsize() const {
int count = 0;
Node<T>* current = head->next;
while (current) {
count++;
current = current->next;
}
return count;
}
// 清空链表
void clear() {
destroy(head->next); // 销毁链表中的所有节点
head->next = nullptr; // 重置头节点的next指针
}
// 插入元素
bool insert(int index, const T& value) {
if (index < 0) return false; // 索引不能为负
Node<T>* current = head;
int currentIndex = 0;
// 找到插入位置的前一个节点
while (current != nullptr && currentIndex < index) {
current = current->next;
currentIndex++;
}
if (current == nullptr) return false; // 索引超出链表范围
// 创建新节点
Node<T>* newNode = new Node<T>;
newNode->data = value;
newNode->next = current->next;
current->next = newNode;
return true;
}
// 删除元素
bool remove(int index) {
if (index < 0) return false; // 索引不能为负
Node<T>* current = head;
int currentIndex = 0;
// 找到删除位置的前一个节点
while (current->next != nullptr && currentIndex < index) {
current = current->next;
currentIndex++;
}
if (current->next == nullptr) return false; // 索引超出链表范围
// 删除节点
Node<T>* temp = current->next;
current->next = temp->next;
delete temp;
return true;
}
// 查找元素
int find(const T& value) const {
Node<T>* current = head->next;
int index = 0;
while (current != nullptr) {
if (current->data == value) {
return index;
}
current = current->next;
index++;
}
return -1; // 未找到
}
// 获取指定位置的元素
bool getvalue(int index, T& value) const {
if (index < 0) return false; // 索引不能为负
Node<T>* current = head->next;
int currentIndex = 0;
while (current != nullptr && currentIndex < index) {
current = current->next;
currentIndex++;
}
if (current == nullptr) return false; // 索引超出链表范围
value = current->data;
return true;
}
// 设置指定位置的元素
bool setvalue(int index, const T& value) {
if (index < 0) return false; // 索引不能为负
Node<T>* current = head->next;
int currentIndex = 0;
while (current != nullptr && currentIndex < index) {
current = current->next;
currentIndex++;
}
if (current == nullptr) return false; // 索引超出链表范围
current->data = value;
return true;
}
// 销毁链表
void destroy(Node<T>*& head) {
Node<T>* temp;
while (head) {
temp = head;
head = head->next;
delete temp;
}
}
// 打印链表
void print() const {
Node<T>* current = head->next;
while (current != nullptr) {
cout << current->data << " ";
current = current->next;
}
cout << endl;
}
//创建链表(头插法)
void creatLnode_1(int n) {
head = new Node<T>; // 创建头节点
head->next = nullptr;
Node<T>* p;
for (int i = 0; i < n; i++) {
p = new Node<T>; // 创建新节点
cin >> p->data; // 从标准输入读取数据
p->next = head->next; // 新节点指向头节点的下一个节点
head->next = p; // 头节点指向新节点
}
}
// 创建链表(尾插法)
void creatLnode_2(int n) {
head = new Node<T>; // 创建头节点
head->next = nullptr;
Node<T>* p, * r;
r = head;
for (int i = 0; i < n; i++) {
p = new Node<T>; // 创建新节点
cin >> p->data; // 从标准输入读取数据
p->next = nullptr;
r->next = p; // 将新节点链接到链表末尾
r = p; // 更新尾指针
}
}
};
int main() {
LinkedList<int> list;
// 测试头插法创建链表
cout << "使用头插法创建链表:" << endl;
int n1;
cout << "请输入链表的长度:";
cin >> n1;
list.creatLnode_1(n1);
cout << "链表内容:";
list.print();
// 测试尾插法创建链表
cout << "\n使用尾插法创建链表:" << endl;
int n2;
cout << "请输入链表的长度:";
cin >> n2;
list.clear(); // 清空链表
list.creatLnode_2(n2);
cout << "链表内容:";
list.print();
// 测试插入元素
cout << "\n插入元素:" << endl;
int index, value;
cout << "请输入插入位置和值:";
cin >> index >> value;
if (list.insert(index, value)) {
cout << "插入成功" << endl;
}
else {
cout << "插入失败" << endl;
}
cout << "链表内容:";
list.print();
// 测试删除元素
cout << "\n删除元素:" << endl;
cout << "请输入删除位置:";
cin >> index;
if (list.remove(index)) {
cout << "删除成功" << endl;
}
else {
cout << "删除失败" << endl;
}
cout << "链表内容:";
list.print();
// 测试查找元素
cout << "\n查找元素:" << endl;
cout << "请输入要查找的值:";
cin >> value;
int foundIndex = list.find(value);
if (foundIndex != -1) {
cout << "元素" << value << "的位置为:" << foundIndex << endl;
}
else {
cout << "元素" << value << "未找到" << endl;
}
// 测试获取指定位置的元素
cout << "\n获取指定位置的元素:" << endl;
cout << "请输入要获取的元素索引:";
cin >> index;
int retrievedValue;
if (list.getvalue(index, retrievedValue)) {
cout << "第" << index << "个元素的值为:" << retrievedValue << endl;
}
else {
cout << "索引超出范围" << endl;
}
// 测试设置指定位置的元素
cout << "\n设置指定位置的元素:" << endl;
cout << "请输入要设置的元素索引和新值:";
cin >> index >> value;
if (list.setvalue(index, value)) {
cout << "设置成功" << endl;
}
else {
cout << "设置失败" << endl;
}
cout << "\n清空链表:" << endl;
list.clear();
cout << "清空链表后,链表是否为空:" << (list.isempty() ? "是" : "否") << endl;
return 0;
}
栈
//栈-顺序存储模式+应用案例
//注意:我这里初始化top=-1可以用,但是不符合数据结构老师的规范,不要写进实验报告里面
#include<iostream>
using namespace std;
template<typename T>
struct Sqstack {
T* data;
int top;
int capacity;
};
template<typename T>
Sqstack<T>* initstack() { //初始化栈
Sqstack<T> *s = new Sqstack<T>();
if (s == nullptr) {
cout << "内存分配失败" << endl;
return nullptr;
}
s->data = new T[100];
s->top = -1;
s->capacity = 100;
return s;
}
template<typename T>
void destroy(Sqstack<T>* s) { //销毁栈
delete[] s->data;
delete s;
}
template<typename T>
void push(Sqstack<T>* s, T num) { //入栈
if (s->top == s->capacity-1) { //扩容
cout << "栈满,重新扩容" << endl;
T* newdata = new T[2 * s->capacity];
for (int i = 0; i < s->top; i++) {
newdata[i] = s->data[i];
}
delete[] s->data;
s->data = newdata;
s->capacity *= 2;
}
s->data[++s->top] = num;
}
template<typename T>
void pop(Sqstack<T>* s, T& e) { //出栈,并用e返回
if (s->top == -1) {
cout << "栈为空,删除失败" << endl;
return;
}
e = s->data[s->top--];
}
template<typename T>
T gettop(Sqstack<T> s) { //获取栈顶元素
if (s.top == -1) {
cout << "栈为空,获取失败" << endl;
return;
}
return s.data[s.top];
}
template<typename T>
bool isempty(Sqstack<T> s) { //判断栈是否为空
return s.top == -1;
}
template<typename T>
void clear(Sqstack<T>* s) { //清空栈
if (s == nullptr) {
cout << "栈为空,清空失败" << endl;
return;
}
s->top = -1;
}
template<typename T>
int length(Sqstack<T> s) { //获取栈的长度
return s.top + 1;
}
template<typename T>
void prints(Sqstack<T> *s) { //打印栈中的元素
if (s == nullptr) {
cout << "空栈,打印失败" << endl;
return;
}
for (int i = 0; i <= s->top; i++) {
cout << s->data[i] << " ";
}
cout << endl;
}
//---------数值转换---------
void conversion(int N) { //输入一个非负十进制数,转化为8进制
Sqstack<int>* s = initstack<int>();
while (N) {
push(s, N % 8);
N /= 8;
}
int e = 0;
while (!isempty(*s)) {
pop(s, e);
cout << e;
}
cout << endl;
}
//---括号算法的匹配---
bool validateBrackets(const string s) {
int n = s.size();
Sqstack<char>* stacks = initstack<char>(); //这里默认创建成功
for (char c : s) { //加强型循环(也称for-each循环)
switch (c) {
case '[':
case '{':
case '(':
push(stacks, c); break;
case ')': {
char temp;
if (isempty(*stacks) || gettop(*stacks) != '(')
return false;
pop(stacks, temp);
break;
}
case ']': {
char temp;
if (isempty(*stacks) || gettop(*stacks) != ']')
return false;
pop(stacks, temp);
break;
}
case '}': {
char temp;
if (isempty(*stacks) || gettop(*stacks) != '}')
return false;
pop(stacks, temp);
break;
}
default:
break;
}
}
return isempty(*stacks); //输入完s后判断栈类是否还有操作符
}
//--------行编辑程序-----------
void editline(string s) {
Sqstack<char>* stacks = initstack<char>(); //默认创建成功哈
char ch, temp;
cin >> ch;
while (ch != EOF) {
while (ch != '\n') {
switch (ch) {
case '#':pop(stacks, temp); //由于函数需要添加了temp
case '@':clear(stacks);
default:push(stacks, ch);
}
cin >> ch;
}
//这里需要一个函数将你的栈中元素上传到数据区
//清空栈
clear(stacks);
if (ch != EOF) cin >> ch;
}
destroy(stacks);
}
//--------表达式求值-----------
int precedence(char op) { // 定义操作符的优先级
switch (op) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
char precedences(char op1, char op2) { // 比较两个操作符的优先级
int p1 = precedence(op1);
int p2 = precedence(op2);
if (p1 > p2) {
return '>';
}
else if (p1 < p2) {
return '<';
}
else {
return '=';
}
}
int applyOp(int a, int b, char op) { // 应用操作符
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/':
if (b == 0) throw runtime_error("Division by zero");
return a / b;
default:
throw runtime_error("Invalid operator");
}
}
int evaluateExpression() { // 表达式求值
stack<char> s1; // 运算符栈
stack<int> s2; // 运算数栈
s1.push('#'); // 初始符号
char c;
while (cin >> c) {
if (isdigit(c)) {
s2.push(c - '0'); // 将字符转换为整数
}
else {
switch (precedences(s1.top(), c)) {
case '<': {
s1.push(c);
break;
}
case '=': {
s1.pop();
break;
}
case '>': {
char op = s1.top();
s1.pop();
int b = s2.top();
s2.pop();
int a = s2.top();
s2.pop();
s2.push(applyOp(a, b, op));
break;
}
}
}
}
return s2.top();
}
int main() {
Sqstack<int>* s = initstack<int>(); // 初始化栈
if (s == nullptr) {
cout << "初始化栈失败" << endl;
return 1;
}
// 测试入栈
cout << "测试入栈:" << endl;
push(s, 10);
push(s, 20);
push(s, 30);
prints(s); // 打印栈内容
// 测试获取栈顶元素
cout << "测试获取栈顶元素:" << endl;
cout << "栈顶元素为:" << gettop(*s) << endl;
// 测试出栈
cout << "测试出栈:" << endl;
int popElement;
pop(s, popElement);
cout << "出栈元素为:" << popElement << endl;
prints(s); // 打印栈内容
// 测试判断栈是否为空
cout << "测试判断栈是否为空:" << endl;
if (isempty(*s)) {
cout << "栈为空" << endl;
}
else {
cout << "栈不为空" << endl;
}
// 测试清空栈
cout << "测试清空栈:" << endl;
clear(s);
prints(s); // 打印栈内容
// 测试获取栈长度
cout << "测试获取栈长度:" << endl;
cout << "栈的长度为:" << length(*s) << endl;
// 测试扩容
cout << "测试扩容:" << endl;
for (int i = 0; i < 150; i++) {
push(s, i);
}
prints(s); // 打印栈内容
// 销毁栈
destroy(s);
return 0;
}
//栈--链式存储结构
#include<iostream>
using namespace std;
template<typename T>
struct StackNode {
T data;
StackNode<T>* next;
};
template<typename T>
struct Linklist {
StackNode<T>* top;
int count;
};
template<typename T>
Linklist<T>* init() { //初始化
Linklist<T>* s = new Linklist<T>();
if (s == nullptr) {
cout << "栈创建失败,呜呜呜" << endl;
return nullptr;
}
s->top = nullptr;
s->count = 0;
return s;
}
template<typename T>
void destroy(Linklist<T>* s) { //销毁
if (s == nullptr) {
cout << "栈指针为空,无需销毁" << endl;
return;
}
StackNode<T>* current = s->top;
while (current) {
StackNode<T>* next = current->next;
delete current;
current = next;
}
delete s;
}
template<typename T>
void push(Linklist<T>* s, T data) { //入栈,栈的链式存储结构理论上来说没有容量限制,可以存储任意多个(只要内存够)
if (s == nullptr) {
cout << "栈指针为空,无需销毁" << endl;
return;
}
StackNode<T>* temp = new StackNode<T>();
temp->data = data;
temp->next = s->top;
s->top = temp;
s->count++;
}
template<typename T>
void pop(Linklist<T>* s, T& e) { //出栈
if (s == nullptr) {
cout << "栈指针为空" << endl;
return;
}
if (s->top == nullptr) {
cout << "空栈,无法出栈" << endl;
return;
}
e = s->top->data;
StackNode<T>* node = s->top;
s->top = s->top->next;
delete node;
}
template<typename T>
T gettop(Linklist<T>* s) { //获取栈顶元素
if (s == nullptr) {
cout << "栈指针为空" << endl;
return T(); // 返回默认构造的T类型值,把该类型看成一个类
}
if (s->top == nullptr) {
cout << "空栈,没有栈顶元素" << endl;
return T();
}
return s->top->data;
}
template<typename T>
bool isempty(Linklist<T>* s) { //判断栈空
return s->top == nullptr;
}
template<typename T>
void clear(Linklist<T>* s) { //清空栈
if (s == nullptr) {
cout << "栈指针为空" << endl;
return;
}
if (s->top == nullptr) {
cout << "空栈,无需清空" << endl;
return;
}
cout << "清空栈中所有元素" << endl;
StackNode<T>* current = s->top;
while (current) {
StackNode<T>* next = current->next;
delete current;
current = next;
}
s->top = nullptr;
s->count = 0;
}
template<typename T>
int length(Linklist<T>* s) { //返回栈中元素的长度
if (s == nullptr) {
cout << "栈指针为空" << endl;
return 0;
}
int sum = 0;
StackNode<T>* node = s->top;
while (node) {
sum++;
node = node->next;
}
return sum;
}
template<typename T>
void prints(Linklist<T>* s) { //打印栈中元素
if (s == nullptr) {
cout << "栈指针为空" << endl;
return;
}
if (s->top == nullptr) {
cout << "空栈,无元素可打印" << endl;
return;
}
cout << "栈中的元素为:";
StackNode<T>* node = s->top;
while (node) {
cout << node->data << " ";
node = node->next;
}
cout << endl; // 在函数末尾添加换行符
}
int main() {
Linklist<int>* s = init<int>(); // 初始化栈
if (s == nullptr) {
cout << "初始化栈失败" << endl;
return 1;
}
// 测试入栈
cout << "测试入栈:" << endl;
push(s, 10);
push(s, 20);
push(s, 30);
prints(s); // 打印栈内容
// 测试获取栈顶元素
cout << "测试获取栈顶元素:" << endl;
int topElement = gettop(s);
cout << "栈顶元素为:" << topElement << endl;
// 测试出栈
cout << "测试出栈:" << endl;
int popElement;
pop(s, popElement);
cout << "出栈元素为:" << popElement << endl;
prints(s); // 打印栈内容
// 测试判断栈是否为空
cout << "测试判断栈是否为空:" << endl;
if (isempty(s)) {
cout << "栈为空" << endl;
}
else {
cout << "栈不为空" << endl;
}
// 测试获取栈长度
cout << "测试获取栈长度:" << endl;
cout << "栈的长度为:" << length(s) << endl;
// 测试清空栈
cout << "测试清空栈:" << endl;
clear(s);
prints(s); // 打印栈内容
// 再次测试获取栈长度
cout << "测试获取栈长度:" << endl;
cout << "栈的长度为:" << length(s) << endl;
// 测试销毁栈
cout << "测试销毁栈:" << endl;
destroy(s);
return 0;
}
队列
//队列--链式存储结构
#include<iostream>
using namespace std;
template<typename T>
struct Qnode {
T data;
Qnode<T>* next;
};
template<typename T>
struct QueueList {
Qnode<T>* front; //队头指针,为了操作方便,front指向头结点
Qnode<T>* rear; //队尾指针
};
template<typename T>
void initQueue(QueueList<T>* list) { //初始化队列
if (list == nullptr) {
cout << "空队列,无法初始化" << endl;
return;
}
list->front = new Qnode<T>();
if (list->front == nullptr) {
cout << "内存分配失败" << endl;
return;
}
list->front->next = nullptr;
list->rear = list->front;
}
template<typename T>
void clearQueue(QueueList<T>* list) { //清空队列
if (list == nullptr || list->front == nullptr) {
return;
}
Qnode<T>* p = list->front->next;
while (p != nullptr) {
Qnode<T>* temp = p;
p = p->next;
delete temp;
}
list->front->next = nullptr;
list->rear = list->front;
}
template<typename T>
void destroyQueue(QueueList<T>* list) { //销毁队列
if (list == nullptr) return;
clearQueue(list);
delete list->front; //销毁和清空的区别
}
template<typename T>
bool queueEmpty(QueueList<T>* list) {
if (list == nullptr || list->front == nullptr) {
return true;
}
return list->front->next == nullptr;
}
template<typename T>
int queueLength(QueueList<T>* list) {
if (list == nullptr || list->front == nullptr ) return 0; //nullptr是c++风格的,相当于c里面的NULL
int ans = 0;
Qnode<T>* p = list->front->next;
while (p) {
ans++;
p = p->next;
}
return ans;
}
template<typename T>
T getHead(QueueList<T>* list) {
if (list == nullptr || list->front == nullptr || list->front->next == nullptr) {
throw out_of_range("队列为空,无法获取队头元素"); //因为这里不好return ,所以我们可以抛出一个异常
}
return list->front->next->data;
}
template<typename T>
void enQueue(QueueList<T>* list, T data){
if (list == nullptr || list->front == nullptr) {
cout << "链表为空,无法入队" << endl;
return;
}
Qnode<T>* p = new Qnode<T>();
p->data = data;
p->next = nullptr;
if (list->front->next == nullptr) { //空队列
list->front->next = p;
list->rear = p;
}
else {
list->rear->next = p;
list->rear = p;
}
}
template<typename T>
void deQueue(QueueList<T>* list, T& e) {
if (list == nullptr || list->front == nullptr || list->front->next == nullptr) {
cout << "空指针或者空队列,无法删除" << endl;
return;
}
Qnode<T>* p = list->front->next;
list->front->next = p->next;
e = p->data;
if (list->front->next == nullptr) list->rear = list->front;
delete p;
}
template<typename T>
void printQueue(QueueList<T>* list) {
if (list == nullptr || list->front == nullptr) {
cout << "空队列" << endl;
return;
}
cout << "队列中的元素为:";
Qnode<T>* p = list->front->next;
while (p) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
int main() {
QueueList<int> list;
initQueue(&list);
try {
cout << "请输入元素个数:";
int n; cin >> n;
cout << "请输入元素:";
for (int i = 0; i < n; i++) {
int a;
cin >> a;
enQueue(&list, a);
}
printQueue(&list); // 打印队列
int e;
deQueue(&list, e);
cout << "出队元素: " << e << endl;
printQueue(&list); // 再次打印队列
cout << "队头元素为:" << getHead(&list) << endl;
deQueue(&list, e);
cout << "出队元素: " << e << endl;
printQueue(&list); // 再次打印队列
cout << "队头元素为:" << getHead(&list) << endl;
deQueue(&list, e);
cout << "出队元素: " << e << endl;
printQueue(&list); // 再次打印队列
if (queueEmpty(&list)) {
cout << "队列为空" << endl;
}
destroyQueue(&list);
}
catch (const out_of_range& e) {
cout << "错误: " << e.what() << endl;
}
return 0;
}
//队列--顺序存储结构
//由于如果单独普通队列意义不大,我们直接从循环队列开干
#include<bits/stdc++.h>
using namespace std;
const int MAX_SIZE = 1000;
template<typename T>
struct Squeue {
T *data;
int front, rear;
};
template<typename T>
void initSqueue(Squeue<T>* s) {
s->data = new T[MAX_SIZE];
if (s->data == nullptr) {
cout << "内存分配失败" << endl;
return;
}
s->front = s->rear = 0;
}
template<typename T>
int queueLength(Squeue<T>* s) {
if (s == nullptr) {
throw invalid_argument("队列对象为空");
}
return (s->rear - s->front + MAX_SIZE) % MAX_SIZE;
}
template<typename T>
void clearSqueue(Squeue<T>* s) {
if (s == nullptr) {
throw invalid_argument("队列对象为空,无法清空");
}
s->front = 0;
s->rear = 0;
}
template <typename T>
void destroySqueue(Squeue<T>* s) {
if (s == nullptr) {
throw invalid_argument("队列对象为空,无法清空");
}
delete[] s->data;
s->front = 0;
s->rear = 0;
}
template<typename T>
bool squeueEmpty(Squeue<T>* s) {
if (s == nullptr) throw std::invalid_argument("队列对象为空");
return (s->rear - s->front + MAX_SIZE) % MAX_SIZE == 0;
}
template<typename T>
T getHead(Squeue<T>* s) {
if (s == nullptr) throw std::invalid_argument("队列对象为空");
if (s->front == s->rear) {
throw out_of_range("空队列,无法获取首元素");
}
return s->data[s->front];
}
template<typename T>
void enSqueue(Squeue<T>* s, T data) {
if (s == nullptr) throw std::invalid_argument("队列对象为空");
if ((s->rear + 1) % MAX_SIZE == s->front)
throw out_of_range("队列已满,无法继续扩充元素");
s->data[s->rear] = data;
s->rear = (s->rear + 1) % MAX_SIZE;
}
template<typename T>
void deSqueue(Squeue<T>* s, T& e) {
if (s == nullptr) throw std::invalid_argument("队列对象为空");
if (s->rear == s->front)
throw out_of_range("队列为空,无法删除元素");
e = s->data[s->front];
s->front = (s->front + 1) % MAX_SIZE;
}
int main() {
Squeue<int> s;
int choice, data;
try {
// 初始化队列
initSqueue(&s);
cout << "队列初始化成功" << endl;
while (true) {
cout << "\n队列操作菜单:" << endl;
cout << "1. 入队" << endl;
cout << "2. 出队" << endl;
cout << "3. 获取队头元素" << endl;
cout << "4. 检查队列是否为空" << endl;
cout << "5. 清空队列" << endl;
cout << "6. 销毁队列并退出" << endl;
cout << "请输入您的选择:";
cin >> choice;
switch (choice) {
case 1: // 入队
cout << "请输入要入队的元素:";
cin >> data;
enSqueue(&s, data);
cout << "入队成功,当前队列长度为: " << queueLength(&s) << endl;
break;
case 2: // 出队
if (squeueEmpty(&s)) {
cout << "队列为空,无法出队" << endl;
}
else {
deSqueue(&s, data);
cout << "出队元素: " << data << endl;
cout << "当前队列长度为: " << queueLength(&s) << endl;
}
break;
case 3: // 获取队头元素
if (squeueEmpty(&s)) {
cout << "队列为空,无法获取队头元素" << endl;
}
else {
data = getHead(&s);
cout << "队头元素为: " << data << endl;
}
break;
case 4: // 检查队列是否为空
if (squeueEmpty(&s)) {
cout << "队列为空" << endl;
}
else {
cout << "队列不为空,当前队列长度为: " << queueLength(&s) << endl;
}
break;
case 5: // 清空队列
clearSqueue(&s);
cout << "队列已清空" << endl;
break;
case 6: // 销毁队列并退出
destroySqueue(&s);
cout << "队列已销毁,程序退出" << endl;
return 0;
default:
cout << "无效的选择,请重新输入" << endl;
}
system("cls"); //清屏函数
}
}
catch (const std::invalid_argument& e) {
cout << "错误: " << e.what() << endl;
}
catch (const std::out_of_range& e) {
cout << "错误: " << e.what() << endl;
}
return 0;
}
串
//串的基本函数定义
//由于演示需要,混用了c++风格和c风格,如realloc和new、nullptr和NULL,自己编写时需要统一
//尤其要注意终止符'\0',c++中的字符串没有这个概念,c++的string类是一个对象,这里知识配合数据结构演示,c的话要注意
#include<bits/stdc++.h>
using namespace std;
const int MAXSIZE = 1000;
class string { //我们还可以将size不单独出来,直接存放在data[0]里面
char* data;
int size;
int capacity;
public:
string() {
data = new char[MAXSIZE];
data[0] = '\0';
capacity = MAXSIZE;
size = 0;
} //构造函数
// 下面的函数都来自于书上的抽象数据类型里面
void StrAssign(const char *s) {
//一开始想通过s.size()先去判断容量,但因为 const所以不能使用
int i = 0;
while (s[i] != '\0') {
data[size++] = s[i++];
if (i == capacity) { //扩容
char *newdata = new char[capacity * 2];
for (int j = 0; j < MAXSIZE; j++) {
newdata[j] = data[j];
}
delete[] data;
data = newdata;
capacity *= 2;
}
}
data[size] = '\0';
}
void StrCopy(string& s) { //copy
int i = 0;
while (s.data[i] != '\0') {
data[i] = s.data[i];
i++;
}
data[i] = '\0';
size = i;
}
bool StrEmpty() { // 判断是否为空串
if (data[0] == '\0') return true;
else return false;
}
int StrLength() {
return size;
}
int StrCompare(string s) {
char* p1 = data, * p2 = s.data;
while (*p1 && *p2 && *p1 == *p2) {
p1++;
p2++;
}
return (*p1 > *p2) ? 1 : (*p1 < *p2) ? -1 : 0;
}
void clearstring() {
while (*data != '\0') {
*data = '\0';
data++;
}
size = 0;
}
void concat(string s) {
while (!s.StrEmpty()) {
data[size] = *s.data;
s.data++;
size++;
if (size == capacity) {
char* newdata = new char[capacity * 2];
for (int i = 0; i < capacity; i++) {
newdata[i] = data[i];
}
delete[] data;
data = newdata;
capacity *= 2;
}
}
data[size] = '\0';
}
string Substring(int pos, int len) {
string s;
if (pos < 0 || pos > size - len) return s;
int i = 0;
while (i < len ) {
s.data[i] = data[pos + i];
if (i == s.capacity) {
char* newdata = new char[s.capacity * 2];
for (int j = 0; j < s.capacity; j++) {
newdata[i] = s.data[i];
}
delete[] s.data;
s.data = newdata;
s.capacity *= 2;
}
i++;
}
}
int index(string s, int pos = 0) {
if (pos < 0 || pos >= size) return -1;
for (int i = pos; i < size; i++) {
if (data[i] == s.data[0]) {
int j = 0;
while (j < s.size){
if (data[i + j] == s.data[j]) j++;
else break;
}
if (j == s.size) return i;
}
}
return -1;
}
string replace(string x, string y, int pos = 0) {
string result;
if (pos < 0 || pos >= size || x.size == 0) return result;
int current = pos;
while (true) {
int match_pos = index(x, current );
if (match_pos == -1) break;
//拼接字符串段
string temp = Substring(current, match_pos - current);
result.concat(temp);
result.concat(y);
//更新参数
current = match_pos + x.size;
}
string temp = Substring(current, size - current);
result.concat(temp);
return result;
} //替换
void Strinsert(int pos, string s) {
if (pos < 0 || pos > size) return;
int i = 0;
if (size + s.size >= capacity) {
data = (char*)realloc(data, (size + s.size + 1) * sizeof(char)); //通过c语言的realloc函数实现精确扩容,需要添加头文件stdlib.h
if (data == nullptr) { //当然如果为了避免反复扩容可以一次多分配一些内存
cout << "内存分配失败" << endl;
return;
}
capacity = size + s.size + 1;
}
for (int i = size - 1; i >= pos; i--) { //腾出位置给新字符串
data[i + s.size] = data[i];
}
for (int i = 0; i < s.size; i++) {
data[pos + i] = s.data[i];
}
size += s.size;
}
void Strdelete(int pos, int len) {
if (pos < 0 || pos >= size - len || len <= 0) return;
for (int i = pos; i < size - len; i++) {
data[i] = data[i + len];
}
data[size - len] = '\0';
size -= len;
}
int findChar(char c, int pos = 0) {
if (pos < 0 || pos >= size) return -1;
for (int i = pos; i < size; i++) {
if (data[i] == c) return i;
}
return -1;
}
void reverse() {
int left = 0, right = size - 1;
while (left < right) {
char temp = data[left];
data[left] = data[right];
data[right] = temp;
left++;
right--;
}
}
void destroy() {
delete[] data;
data = nullptr;
size = 0;
}
};
int main() {
//测试代码直接用string会和系统的string冲突
//解决方法1
::string s; //通过::指定使用自定义的string类
std::string s; //系统string 类
//解决方法2
//重定义我的类名,不要冲突
return 0;
}
//暴力搜索算法和KMP模式匹配算法
#include<bits/stdc++.h>
using namespace std;
//暴力搜索算法
int bf(string s, string pattern, int pos = 0) {
if (pos < 0 || pos > s.length() || pattern.length() > s.length()) return -1;
if (pattern.length() == 0) return 0;
for (int i = pos; i < s.length() - pattern.length(); i++) {
int temp = i, j = 0;
for (; j < pattern.length(); j++) {
if (s[temp] == pattern[j]) {
temp++;
}
else {
break;
}
}
if (j == pattern.length()) {
return i;
}
}
return -1;
}
//更新前的回溯函数
void get_next(string pattern, int*& next) {
int len = pattern.length();
next = new int[len];
next[0] = -1;
int i = 0;
int j = -1;
while (i < len - 1) { // 确保i+1不越界
if (j == -1 || pattern[i] == pattern[j]) {
i++;
j++;
next[i] = j;
}
else {
j = next[j];
}
}
}
//更新后的回溯函数
void get_nextval(string pattern, int*& nextval) {
int i = 0, j = -1;
int len = (int)pattern.length();
nextval = new int[len];
nextval[0] = -1;
while (i < len - 1) {
if (j == -1 || pattern[i] == pattern[j]) {
i++; j++;
if (pattern[i] != pattern[j]) nextval[i] = j;
else nextval[i] = nextval[j];
}
else j = nextval[j];
}
}
//KMP模式匹配算法
int kmp(string s, string pattern, int pos = 0) {
int s_len = (int)s.length();
int p_len = (int)pattern.length();
if (pos < 0 || pos > s_len || p_len > s_len) return -1;
if (pattern.empty()) return 0;
int* next = nullptr;
get_next(pattern, next);
int i = pos, j = -1;
while (i < s_len && j < p_len) {
if ( j == -1 || s[i] == pattern[j]) {
i++; j++;
}
else {
j = next[j];
}
}
delete[] next;
return (j == p_len) ? (i - j) : -1;
}
int main() {
string aa = "dfjkdfd";
string pattern = "jkd";
cout << kmp(aa, pattern, 0);
return 0;
}
广义表
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_STR_LEN 1024 //定义最大字符串长度
typedef char* AtomType;//定义原子类型为字符指针
typedef enum { ATOM, LIST } ElemTag;
typedef struct GLNode
{
ElemTag tag; //节点类型标记(ATOM或LIST)
union
{
AtomType atom; //原子节点值
struct
{
struct GLNode* hp; //表头指针
struct GLNode* tp; //表尾指针
} ptr;
};
} GLNode, * GList;
//去除字符串中的所有空格
void remove_spaces(char* str)
{
if (!str) return; //安全检查
char* p = str, * q = str;
while (*p)
{
if (!isspace(*p)) *q++ = *p; //只保留非空格字符
p++;
}
*q = '\0'; //添加字符串结束符
}
//判断字符串类型:空表('N')、原子串('E')或其他形式('O')
char test(const char* s)
{
if (!s || s[0] == '\0') return 'N'; //空指针或空串
for (int i = 0; s[i]; i++)
{
if (s[i] == '(' || s[i] == ')' || s[i] == ',')
return 'O'; //包含括号或逗号
}
return 'E'; //纯原子字符串
}
//获取子串中的第一项
void hsub(const char* s, char* h)
{
int level = 0; //括号嵌套层级计数器
const char* p = s;
char* q = h;
while (*p)
{
if (*p == '(') level++; //遇到左括号增加层级
else if (*p == ')') level--; //遇到右括号减少层级
else if (*p == ',' && level == 0) break; //顶层逗号分割点
*q++ = *p++; //复制字符
}
*q = '\0'; //结束字符串
}
//获取子串中除第一项外的剩余部分
void tsub(const char* s, char* t)
{
int level = 0;
const char* p = s;
char* q = t;
while (*p)
{
if (*p == '(') level++;
else if (*p == ')') level--;
else if (*p == ',' && level == 0)
{
p++; //跳过分割逗号
break;
}
p++;
}
while (*p) *q++ = *p++; //复制剩余部分
*q = '\0';
}
//创建空表节点
GList CreateGList()
{
GList L = (GList)malloc(sizeof(GLNode));
if (!L) return NULL;
L->tag = LIST; //标记为列表类型
L->ptr.hp = L->ptr.tp = NULL; //初始化表头表尾为空
return L;
}
//递归构建广义表
GList BuildGList(const char* s)
{
if (!s || strlen(s) == 0 || strcmp(s, "()") == 0)//处理空表情况
return CreateGList();
char type = test(s);
if (type == 'N') return CreateGList();
if (type == 'E') //处理原子节点
{
GList L = (GList)malloc(sizeof(GLNode));
L->tag = ATOM;
L->atom = _strdup(s); //复制原子字符串
return L;
}
char* content = _strdup(s);//处理列表情况
if (content[0] == '(' && content[strlen(content) - 1] == ')') //去掉外层括号
{
content[strlen(content) - 1] = '\0';
memmove(content, content + 1, strlen(content));
}
GList L = CreateGList(); //创建列表节点
if (!L) return NULL;
GList* current = &(L->ptr.hp); //当前插入位置指针
char* rest = _strdup(content); //剩余待处理字符串
while (strlen(rest) > 0) //分割出当前项和剩余部分
{
char* h = (char*)malloc(strlen(rest) + 1);
char* t = (char*)malloc(strlen(rest) + 1);
hsub(rest, h);
tsub(rest, t);
GList node = (GList)malloc(sizeof(GLNode));//创建新节点并构建子表
node->tag = LIST;
node->ptr.hp = BuildGList(h); //递归构建子表
node->ptr.tp = NULL;
*current = node;//将新节点链接到当前列表
current = &(node->ptr.tp); //移动当前指针
free(rest);
rest = _strdup(t);
free(h);
free(t);
}
free(rest);
free(content);
return L;
}
//获取表头指针
GList GetHead(GList L)
{
if (!L || L->tag != LIST) return NULL;
return L->ptr.hp ? L->ptr.hp->ptr.hp : NULL;
}
//获取表尾指针
GList GetTail(GList L)
{
if (!L || L->tag != LIST) return NULL;
if (!L->ptr.hp || !L->ptr.hp->ptr.tp) return NULL;
GList tail = (GList)malloc(sizeof(GLNode)); //创建新节点表示表尾
tail->tag = LIST;
tail->ptr.hp = L->ptr.hp->ptr.tp; //表尾作为新表头
tail->ptr.tp = NULL;
return tail;
}
//递归释放广义表内存
void FreeGList(GList L)
{
if (!L) return;
if (L->tag == ATOM)
free(L->atom); //释放原子字符串
else
{
FreeGList(L->ptr.hp); //递归释放表头
FreeGList(L->ptr.tp); //递归释放表尾
}
free(L); //释放节点本身
}
//递归打印广义表
void PrintGList(GList L)
{
if (!L)
{
printf("()"); //空指针打印空表
return;
}
if (L->tag == ATOM)
{
printf("%s", L->atom); //原子直接打印
return;
}
printf("(");// 列表打印
GList p = L->ptr.hp;
while (p)
{
PrintGList(p->ptr.hp); //递归打印表头
if (p->ptr.tp) printf(","); //元素间用逗号分隔
p = p->ptr.tp; //移动到下一个元素
}
printf(")");
}
int main()
{
char input[MAX_STR_LEN] = { 0 }; //输入缓冲区
char buffer[MAX_STR_LEN]; //临时缓冲区
char operations[MAX_STR_LEN]; //操作序列缓冲区
printf("请输入广义表(可以多行输入,以空行结束):\n");//读取多行输入直到空行
while (fgets(buffer, MAX_STR_LEN, stdin))
{
if (buffer[0] == '\n') break;
strcat(input, buffer);
}
remove_spaces(input);
GList L = BuildGList(input);
if (!L)
{
printf("错误: 构建广义表失败,请检查格式\n");
return 1;
}
printf("构建的广义表为: ");
PrintGList(L);
printf("\n");
printf("请输入操作序列(h表示head,t表示tail,例如tth): ");
if (!fgets(operations, MAX_STR_LEN, stdin))
{
FreeGList(L);
return 1;
}
operations[strcspn(operations, "\n")] = '\0';
GList current = L;
printf("操作过程:\n");
if (strlen(operations) == 0)
{
PrintGList(current);
printf("\n");
}
else
{
for (int i = 0; operations[i]; i++)
{
if (operations[i] == 'h')
{
current = GetHead(current);
printf("h -> ");
}
else if (operations[i] == 't')
{
current = GetTail(current);
printf("t -> ");
}
else
{
printf("错误: 无效操作 '%c'\n", operations[i]);
FreeGList(L);
return 1;
}
if (!current)
{
printf("NULL\n");
break;
}
PrintGList(current);
printf("\n");
}
}
FreeGList(L);
return 0;
}
树
- 二叉树
//二叉树结构
//树的结构一般都是用递归的思想来实现的
#include<stdio.h>
#include<stdlib.h> //malloc的头文件
typedef struct BiTNode {
int data; //如果需要可以改为其他类型数据如char类型
struct BiTNode* lchild, * rchild;
}BiTNode,*BiTree;
int CreateBiTree(BiTree* T) { //创建二叉树
int x;
scanf("%d", &x);
if (x == 0) { //0表示空结点
T == NULL;
}
else {
*T = (BiTree)malloc(sizeof(BiTNode));
if (!*T) {
printf("内存分配失败\n");
return 0;
}
(*T)->data = x;
CreateBiTree(&(*T)->lchild); //递归创建左子树
CreateBiTree(&(*T)->rchild); //递归创建右子树
}
return 1;
}
//先序遍历
int PreOrderTraverse(BiTree T) {
if (T == NULL) {
return 0;
}
printf("%d ", T->data); //访问根结点
PreOrderTraverse(T->lchild); //遍历左子树
PreOrderTraverse(T->rchild); //遍历右子树
return 1;
}
//中序遍历
int InOrderTraverse(BiTree T) {
if (T == NULL) {
return 0;
}
InOrderTraverse(T->lchild); //遍历左子树
printf("%d ", T->data); //访问根结点
InOrderTraverse(T->rchild); //遍历右子树
return 1;
}
//后序遍历
int PostOrderTraverse(BiTree T) {
if (T == NULL) {
return 0;
}
InOrderTraverse(T->lchild); //遍历左子树
InOrderTraverse(T->rchild); //遍历右子树
printf("%d ", T->data); //访问根结点
return 1;
}
//非递归思想先序遍历(栈)
int PreOrderTraverseStack(BiTree T) {
if (T == NULL) {
return 0;
}
BiTree stack[100]; //栈
int top = -1; //栈顶指针
stack[++top] = T; //将根结点入栈
while (top != -1) { //栈不空
BiTree p = stack[top--]; //出栈
printf("%d ", p->data); //访问结点
if (p->rchild) { //如果有右子树
stack[++top] = p->rchild; //入栈
}
if (p->lchild) { //如果有左子树
stack[++top] = p->lchild; //入栈
}
}
return 1;
}
//层序遍历
int LevelOrderTraverse(BiTree T) {
if (T == NULL) {
return 0;
}
BiTree queue[100]; //队列
int front = 0, rear = 0; //队头和队尾指针
queue[rear++] = T; //将根结点入队
while (front != rear) { //队列不空
BiTree p = queue[front++]; //出队
printf("%d ", p->data); //访问结点
if (p->lchild) { //如果有左子树
queue[rear++] = p->lchild; //入队
}
if (p->rchild) { //如果有右子树
queue[rear++] = p->rchild; //入队
}
}
return 1;
}
//求二叉树的深度
int Depth(BiTree T) {
if (T == NULL) {
return 0;
}
int ldepth = Depth(T->lchild); //左子树深度
int rdepth = Depth(T->rchild); //右子树深度
return (ldepth > rdepth ? ldepth : rdepth) + 1; //返回较大值加1
}
//求二叉树的结点数
int CountNode(BiTree T) {
if (T == NULL) {
return 0;
}
return CountNode(T->lchild) + CountNode(T->rchild) + 1; //返回左子树结点数加右子树结点数加1
}
//求二叉树的叶子结点数
int CountLeaf(BiTree T) {
if (T == NULL) {
return 0;
}
if (T->lchild == NULL && T->rchild == NULL) { //如果是叶子结点
return 1;
}
return CountLeaf(T->lchild) + CountLeaf(T->rchild); //返回左子树叶子结点数加右子树叶子结点数
}
int main() {
return 0;
}
- 二叉线索树(以中序遍历为例)
#include <stdio.h>
#include <stdlib.h>
typedef enum PointerTag { Link, Thread };
typedef struct BiThrNode {
int data;
struct BiThrNode* lchild, * rchild;
PointerTag Ltag, Rtag;
} BiThrNode, * BiThrTree;
void CreateBiTree(BiThrTree* T) {
int x;
scanf_s("%d", &x); // 使用scanf_s需根据编译器调整
if (x == 0) {
*T = NULL;
}
else {
*T = (BiThrNode*)malloc(sizeof(BiThrNode));
if (*T == NULL) {
printf("内存分配失败\n");
return;
}
(*T)->data = x;
(*T)->Ltag = Link; // 初始化标签
(*T)->Rtag = Link;
CreateBiTree(&(*T)->lchild);
CreateBiTree(&(*T)->rchild);
}
}
void InOrderThread(BiThrTree* p, BiThrNode** pre) {
if (*p != NULL) {
InOrderThread(&(*p)->lchild, pre);
// 处理当前节点的前驱线索
if ((*p)->lchild == NULL) {
(*p)->Ltag = Thread;
(*p)->lchild = *pre;
}
// 处理前驱节点的后继线索
if (*pre != NULL && (*pre)->rchild == NULL) {
(*pre)->Rtag = Thread;
(*pre)->rchild = *p;
}
*pre = *p; // 更新前驱
InOrderThread(&(*p)->rchild, pre);
}
}
void InOrderTraverseThread(BiThrNode* root) {
BiThrNode* p = root;
while (p != NULL) {
// 找到最左节点
while (p->Ltag == Link) {
p = p->lchild;
}
printf("%d ", p->data);
// 沿后继访问
while (p->Rtag == Thread && p->rchild != NULL) {
p = p->rchild;
printf("%d ", p->data);
}
p = p->rchild; // 处理右子树
}
}
int main() {
BiThrTree root = NULL;
printf("请输入二叉树的节点数据(0表示空节点,前序遍历方式):\n");
CreateBiTree(&root);
BiThrNode* pre = NULL;
InOrderThread(&root, &pre);
// 处理最后一个节点的后继线索
if (pre != NULL) {
pre->Rtag = Thread;
pre->rchild = NULL;
}
printf("中序线索二叉树的中序遍历结果:\n");
InOrderTraverseThread(root);
printf("\n");
return 0;
}
- 树的结构及树转化为二叉树(以第三种树存储方式为例)
//树的存储结构
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100
/*
双亲表示法
用一维数组的方式存储树结构,每个元素有两个属性,data和parent
通过data表示该点的值,通过parent表示该点的父节点
*/
typedef struct PTNode { //结点结构定义
int data;
int parent;
}PTNode;
typedef struct PTree { //树的存储结构
PTNode nodes[MAX_SIZE];
int r,n; //根的位置和结点数
}PTree;
/*
孩子表示法
同样使用一维数组的方式存储树结构,每个元素有两个属性,data和firstchild
firstchild表示该点的第一个孩子结点,孩子结点用链表的方式存储
*/
typedef struct CTNode {
int child;
struct CTNode* next;
}*ChildPtr;
typedef struct CTBox {
int data;
ChildPtr firstchild;
}CTBox;
typedef struct CTree {
CTBox nodes[MAX_SIZE];
int n, r; //结点数,根的位置
}*CTree;
/*
孩子兄弟表示法
*/
typedef struct CSNode {
int data;
struct CSNode* firstchild, * nextsibling;
}CSNode,*CSTree;
// ------------------------------------
typedef struct BiTNode { //补充的二叉树的定义
int data;
struct BiTNode* lchild;
struct BiTNode* rchild;
} BiTNode, * BiTree;
// 创建二叉树节点
BiTNode* createBiTreeNode(int data) {
BiTNode* newNode = (BiTNode*)malloc(sizeof(BiTNode));
if (!newNode) {
printf("内存分配失败\n");
return NULL;
}
newNode->data = data;
newNode->lchild = NULL;
newNode->rchild = NULL;
return newNode;
}
// 树转换为二叉树
BiTree treeToBinaryTree(CSTree root) {
if (root == NULL) {
return NULL;
}
BiTree binaryRoot = createBiTreeNode(root->data);
if (root->firstchild) {
binaryRoot->lchild = treeToBinaryTree(root->firstchild);
}
CSNode* sibling = root->nextsibling;
while (sibling) {
BiTNode* newNode = createBiTreeNode(sibling->data);
newNode->lchild = sibling->firstchild ? treeToBinaryTree(sibling->firstchild) : NULL;
newNode->rchild = sibling->nextsibling ? treeToBinaryTree(sibling->nextsibling) : NULL;
if (binaryRoot->rchild) {
BiTNode* temp = binaryRoot->rchild;
while (temp->rchild) {
temp = temp->rchild;
}
temp->rchild = newNode;
}
else {
binaryRoot->rchild = newNode;
}
sibling = sibling->nextsibling;
}
return binaryRoot;
}
int main() {
return 0;
}
- 构建哈夫曼树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
// 定义哈夫曼树的节点结构
typedef struct {
int weight; // 节点的权重
int parent, lchild, rchild; // 父节点、左孩子节点、右孩子节点的索引
} HTNode, * HuffmanTree;
// 定义哈夫曼编码的类型为字符指针数组
typedef char** HuffmanCode;
// 从给定的n个节点中选择两个parent为0且weight最小的节点
void Select(HuffmanTree HT, int n, int* s1, int* s2) {
int min1 = INT_MAX, min2 = INT_MAX;
for (int i = 1; i <= n; i++) {
if (HT[i].parent == 0) { // 找到没有被选择过的节点
if (HT[i].weight < min1) {
min2 = min1;
*s2 = *s1;
min1 = HT[i].weight;
*s1 = i;
}
else if (HT[i].weight < min2) {
min2 = HT[i].weight;
*s2 = i;
}
}
}
}
// 创建哈夫曼树并生成哈夫曼编码
void HuffmanCreate(HuffmanTree* HT, HuffmanCode* HC, int* w, int n) {
if (n <= 1) return; // 如果只有一个字符,则不需要编码
int m = 2 * n - 1; // 哈夫曼树的总节点数
*HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode)); // 动态分配哈夫曼树数组
for (int i = 1; i <= n; i++) {
(*HT)[i].weight = w[i - 1]; // 初始化叶子节点的权重
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
for (int i = n + 1; i <= m; i++) {
(*HT)[i].weight = 0;
(*HT)[i].parent = 0;
(*HT)[i].lchild = 0;
(*HT)[i].rchild = 0;
}
// 构建哈夫曼树
for (int i = n + 1; i <= m; i++) {
int s1, s2;
Select(*HT, i - 1, &s1, &s2); // 选择两个最小权重的节点
(*HT)[s1].parent = i;
(*HT)[s2].parent = i;
(*HT)[i].lchild = s1;
(*HT)[i].rchild = s2;
(*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight; // 设置新节点的权重
}
*HC = (HuffmanCode)malloc((n + 1) * sizeof(char*)); // 动态分配哈夫曼编码数组
char* cd = (char*)malloc(n * sizeof(char)); // 临时数组存储单个编码
for (int i = 1; i <= n; i++) {
int start = n - 1;
for (int c = i, f = (*HT)[i].parent; f != 0; c = f, f = (*HT)[f].parent) {
cd[--start] = ((*HT)[f].lchild == c) ? '0' : '1'; // 从根到叶子逆向生成编码
}
(*HC)[i] = (char*)malloc((n - start) * sizeof(char)); // 分配空间存储编码
strcpy_s((*HC)[i], n - start + 1, &cd[start + 1]); // 复制编码到HC数组
}
free(cd); // 释放临时数组
}
int main() {
}
图
- 图的邻接矩阵存储
#include<bits/stdc++.h>
using namespace std;
#define MAX_VERTEX_NUM 20
typedef struct {
char vexs[MAX_VERTEX_NUM]; // 顶点向量
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵
int vexnum, arcnum; // 图的当前顶点数和弧数
}MGraph;
int Locate(MGraph G, char v) {
for (int i = 0; i < G.vexnum; i++) {
if (G.vexs[i] == v) {
return i;
}
}
return -1;
}
int CreateGraph(MGraph& G) {
printf("请输入顶点数和边数:\n");
cin >> G.vexnum >> G.arcnum;
if (G.vexnum <= 0 || G.vexnum > MAX_VERTEX_NUM) {
printf("输入错误!\n");
return 0;
}
printf("请输入顶点信息:\n");
for (int i = 0; i < G.vexnum; i++) {
cin >> G.vexs[i];
}
printf("请输入边的信息:<边1><边2><权值>\n");
for (int i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
G.arcs[i][j] = INT_MAX; //初始化为无穷大
}
}
for (int i = 0; i < G.arcnum; i++) {
char v1, v2;
int w;
cin >> v1 >> v2 >> w; //输入边的两个顶点和权值
int p1 = Locate(G, v1);
int p2 = Locate(G, v2);
if (p1 == -1 || p2 == -1) {
printf("顶点信息输入错误\n");
return 0;
}
G.arcs[p1][p2] = w;
G.arcs[p2][p1] = w;
}
printf("无向图创建成功!\n");
return 1;
}
void PrintGraph(MGraph G) {
printf("图的顶点信息为:\n");
for (int i = 0; i < G.vexnum; i++) {
printf("%c ", G.vexs[i]);
}
printf("\n图的邻接矩阵为:\n");
for (int i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
if (G.arcs[i][j] == INT_MAX) {
printf("∞ ");
}
else {
printf("%d ", G.arcs[i][j]);
}
}
printf("\n");
}
}
int main() {
MGraph G;
if (CreateGraph(G)) {
PrintGraph(G);
}
else {
printf("图创建失败!\n");
}
return 0;
}
- 图的邻接表存储
#include<bits/stdc++.h>
using namespace std;
#define MAX_VERTEX_NUM 20
typedef struct ArcNode { // 弧结点
int adjvex; // 弧头下标
struct ArcNode* nextarc;
int weight; // 权值
}ArcNode;
typedef struct VNode { //顶点结点
char data;
struct ArcNode* firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct { //图
AdjList vertices; // 顶点向量
int vexnum, arcnum; // 图的当前顶点数和弧数
}AlGraph;
int Locate(AlGraph G, char v) { // 查找顶点下标
for (int i = 0; i < G.vexnum; i++) {
if (G.vertices[i].data == v) {
return i;
}
}
return -1;
}
int CreateGraph(AlGraph& G) {
printf("请输入顶点数和边数:\n");
cin >> G.vexnum >> G.arcnum;
if (G.vexnum <= 0 || G.vexnum > MAX_VERTEX_NUM) {
printf("输入错误!\n");
return 0;
}
printf("请输入顶点信息:\n"); // 初始化
for (int i = 0; i < G.vexnum; i++) {
cin >> G.vertices[i].data;
G.vertices[i].firstarc = nullptr;
}
printf("请输入边的信息:<边1><边2><权值>\n");
for (int i = 0; i < G.arcnum; i++) {
char v1, v2;
int w;
cin >> v1 >> v2 >> w; // 输入边的两个顶点
int p1 = Locate(G, v1); // 查找顶点下标
int p2 = Locate(G, v2);
if (p1 == -1 || p2 == -1) {
printf("顶点信息输入错误\n");
return 0;
}
// 创建弧结点
ArcNode* newArc = new ArcNode;
newArc->weight = w;
newArc->adjvex = p2;
newArc->nextarc = G.vertices[p1].firstarc; //尾插
G.vertices[p1].firstarc = newArc;
newArc = new ArcNode; // 创建另一条弧
newArc->weight = w;
newArc->adjvex = p1;
newArc->nextarc = G.vertices[p2].firstarc;
G.vertices[p2].firstarc = newArc;
}
printf("无向图创建成功!\n");
return 1;
}
void PrintfGraph(AlGraph G) {
printf("图的顶点信息为:\n");
for (int i = 0; i < G.vexnum; i++) {
cout << G.vertices[i].data << " ";
}
printf("\n图的邻接表为:\n");
for (int i = 0; i < G.vexnum; i++) {
cout << G.vertices[i].data << " -> ";
ArcNode* p = G.vertices[i].firstarc;
while (p) {
cout << G.vertices[p->adjvex].data << "(" << p->weight << ") ";
p = p->nextarc;
}
cout << endl;
}
}
bool visited[MAX_VERTEX_NUM];
void DFS(AlGraph G, int v) { //dfs深度优先遍历
visited[v] = true; // 访问标记
cout << G.vertices[v].data << " "; // 访问顶点
ArcNode* p = G.vertices[v].firstarc;
while (p != NULL) {
if (!visited[p->adjvex]) { // 如果未访问
DFS(G, p->adjvex); // 递归访问
}
p = p->nextarc; // 访问下一个邻接点
}
}
void DFSTraverse(AlGraph G) {
for (int i = 0; i < G.vexnum; i++) visited[i] = false; // 初始化
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
DFS(G, i);
cout << endl; // 每个连通分量后换行
}
}
}
void BFS(AlGraph G, int v) {
queue<int> q;
visited[v] = true; // 标记起始顶点为已访问
cout << G.vertices[v].data << " ";
q.push(v); // 将起始顶点入队
while (!q.empty()) {
int u = q.front(); // 取出队列头部元素
q.pop();
ArcNode* p = G.vertices[u].firstarc; // 获取当前顶点的邻接点链表
while (p != NULL) {
if (!visited[p->adjvex]) { // 如果邻接点未被访问
visited[p->adjvex] = true; // 标记为已访问
cout << G.vertices[p->adjvex].data << " ";
q.push(p->adjvex); // 将邻接点入队
}
p = p->nextarc; // 移动到下一个邻接点
}
}
}
void BFSTraverse(AlGraph G) {
for (int i = 0; i < G.vexnum; i++) visited[i] = false; // 初始化
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i]) { // 如果顶点未被访问
BFS(G, i); // 从该顶点开始进行 BFS
cout << endl; // 每个连通分量后换行
}
}
}
int main() {
AlGraph G;
if (CreateGraph(G)) {
PrintfGraph(G);
cout << "深度优先遍历结果:" << endl;
DFSTraverse(G);
cout << endl;
cout << "广度优先遍历结果:" << endl;
BFSTraverse(G);
}
else {
printf("图创建失败!\n");
}
return 0;
}
-
- 图的十字链表存储
#include<bits/stdc++.h>
using namespace std;
#define MAX_VEXTEX_NUM 20
typedef struct ArcBox{ //弧结点
int tailvex, headvex;
struct ArcBox* hlink, * tlink;
int weight;
}ArcBox;
typedef struct VexNode { //顶点结点
char data;
ArcBox* firstin, * firstout;
}VexNode;
typedef struct {
VexNode xlist[MAX_VEXTEX_NUM]; //顶点表
int vexnum, arcnum; //顶点数和弧数
}OLGraph;
int Locate(OLGraph G, char v) {
for (int i = 0; i < G.vexnum; i++) {
if (G.xlist[i].data == v) return i; //返回顶点v在顶点表中的位置
}
return -1;
}
int CreateGraph(OLGraph& G) {
cout << "请输入顶点数和弧数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入顶点信息:";
for (int i = 0; i < G.vexnum; i++) {
cin >> G.xlist[i].data;
G.xlist[i].firstin = nullptr;
G.xlist[i].firstout = nullptr;
}
cout << "请输入弧信息(起点 终点 权重):\n";
for (int i = 0; i < G.arcnum; i++) {
char v1, v2;
int w;
cin >> v1 >> v2 >> w;
int p1 = Locate(G, v1), p2 = Locate(G, v2);
if (p1 == -1 || p2 == -1) {
cout << "顶点不存在!\n";
return 0;
}
ArcBox* newArc = new ArcBox;
newArc->headvex = p2;
newArc->tailvex = p1;
newArc->hlink = G.xlist[p2].firstin;
newArc->tlink = G.xlist[p1].firstout;
newArc->weight = w;
G.xlist[p2].firstin = newArc;
G.xlist[p1].firstout = newArc;
}
}
void PrintGraph(OLGraph G) {
cout << "图的顶点信息为:" << endl;
for (int i = 0; i < G.vexnum; i++) {
cout << G.xlist[i].data << " ";
}
cout << endl;
cout << "图的边信息为:" << endl;
for (int i = 0; i < G.vexnum; i++) {
ArcBox* p = G.xlist[i].firstout;
while (p != nullptr) {
cout << G.xlist[p->tailvex].data << " -> " << G.xlist[p->headvex].data << " (" << p->weight << ") ";
p = p->tlink;
}
cout << endl;
}
}
int main() {
OLGraph G;
if (CreateGraph(G)) {
PrintGraph(G);
}
else {
cout << "图创建失败!\n";
}
return 0;
}
- 图的临界多重表存储(省略)
- 最小生成树
-
普里姆算法(prim)
#include <stdio.h>
#include <limits.h>
#define MAX_VERTEX_NUM 20
#define INF INT_MAX
typedef struct {
int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 邻接矩阵
int numVertices; // 顶点数
int minCost; // 最小生成树的总权重
} Graph;
// 查找最小边的顶点
int minKey(int key[], int mstSet[]) {
int min = INF, min_index;
for (int v = 0; v < MAX_VERTEX_NUM; v++) {
if (mstSet[v] == 0 && key[v] < min) {
min = key[v];
min_index = v;
}
}
return min_index;
}
// 打印生成的最小生成树
void printMST(int parent[], int graph[MAX_VERTEX_NUM][MAX_VERTEX_NUM], int numVertices) {
printf("边 \t权重\n");
for (int i = 1; i < numVertices; i++) {
printf("%d - %d \t%d \n", parent[i], i, graph[i][parent[i]]);
}
}
// 实现普利姆算法
void primMST(Graph* graph) {
int parent[MAX_VERTEX_NUM]; // 存储最小生成树
int key[MAX_VERTEX_NUM]; // 用于选择最小边的键值
int mstSet[MAX_VERTEX_NUM]; // 表示顶点是否已经在最小生成树中
// 初始化所有键值为无穷大,mstSet[] 为 false
for (int i = 0; i < graph->numVertices; i++) {
key[i] = INF;
mstSet[i] = 0;
}
// 总是将第一个顶点作为最小生成树的根节点
key[0] = 0;
parent[0] = -1;
for (int count = 0; count < graph->numVertices - 1; count++) {
// 选择最小键值的顶点,该顶点未包含在 MST 中
int u = minKey(key, mstSet);
// 将选中的顶点添加到最小生成树中
mstSet[u] = 1;
// 更新相邻顶点的键值
for (int v = 0; v < graph->numVertices; v++) {
// 如果 v 在 MST 中,或者不存在从 u 到 v 的边,则不更新
if (graph->edges[u][v] && mstSet[v] == 0 && graph->edges[u][v] < key[v]) {
parent[v] = u;
key[v] = graph->edges[u][v];
}
}
}
// 打印构造的最小生成树
printMST(parent, graph->edges, graph->numVertices);
}
int main() {
Graph graph;
graph.numVertices = 5;
// 邻接矩阵表示的图
int graphEdges[5][5] = {
{0, 2, 0, 6, 0},
{2, 0, 3, 8, 5},
{0, 3, 0, 0, 7},
{6, 8, 0, 0, 9},
{0, 5, 7, 9, 0}
};
graph.edges = graphEdges;
// 调用普利姆算法
primMST(&graph);
return 0;
}
-
克鲁斯卡尔算法(kruskal)
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 20
#define INF 999999
// 定义边的结构体
typedef struct {
int begin; // 边的起点
int end; // 边的终点
int weight; // 边的权重
} Edge;
// 定义子集的结构体,用于管理并查集
typedef struct {
int parent[MAX_VERTEX_NUM]; // 存储每个元素的父节点
int rank[MAX_VERTEX_NUM]; // 存储每个子集的秩
} Subset;
// 查找元素 i 所在的子集的根,并进行路径压缩
int find(Subset subsets, int i) {
if (subsets.parent[i] != i) {
subsets.parent[i] = find(subsets, subsets.parent[i]); // 路径压缩
}
return subsets.parent[i];
}
// 合并两个子集
int unionSets(Subset *subsets, int x, int y) {
int xroot = find(*subsets, x);
int yroot = find(*subsets, y);
if (subsets->rank[xroot] < subsets->rank[yroot])
subsets->parent[xroot] = yroot;
else if (subsets->rank[xroot] > subsets->rank[yroot])
subsets->parent[yroot] = xroot;
else {
subsets->parent[yroot] = xroot;
subsets->rank[xroot]++;
}
}
// 用于 qsort 的比较函数,按边的权重从小到大排序
int compareEdges(const void* a, const void* b) {
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1->weight - b1->weight;
}
// Kruskal算法实现
void KruskalMST(Edge edges[], int numEdges, int numVertices) {
qsort(edges, numEdges, sizeof(Edge), compareEdges); // 对边按权重排序
Subset subsets; // 初始化并查集
for (int v = 0; v < numVertices; ++v) {
subsets.parent[v] = v;
subsets.rank[v] = 0;
}
Edge result[MAX_VERTEX_NUM]; // 存储最小生成树的边
int e = 0; // 最小生成树的边数
for (int i = 0; i < numEdges; ++i) {
Edge next_edge = edges[i];
int x = find(subsets, next_edge.begin);
int y = find(subsets, next_edge.end);
// 如果 x 和 y 不在同一个子集中,则将这条边加入到最小生成树中
if (x != y) {
result[e++] = next_edge;
unionSets(&subsets, x, y);
}
}
// 打印最小生成树的边和权重
printf("边 \t权重\n");
for (int i = 0; i < e; ++i) {
printf("%d - %d \t%d \n", result[i].begin, result[i].end, result[i].weight);
}
}
int main() {
int numVertices = 4; // 顶点数
int numEdges = 5; // 边数
Edge edges[MAX_VERTEX_NUM] = {
{0, 1, 10}, // 边 0-1 权重 10
{0, 2, 6}, // 边 0-2 权重 6
{0, 3, 5}, // 边 0-3 权重 5
{1, 3, 15}, // 边 1-3 权重 15
{2, 3, 4} // 边 2-3 权重 4
};
KruskalMST(edges, numEdges, numVertices); // 调用 Kruskal 算法
return 0;
}
查找
- 顺序查找和折半查找
#include<stdio.h>
#include<stdlib.h>
typedef struct{
int* elem;
int length;
}SSTable;
void init_SSTable(SSTable* ST, int n) {
ST->elem = (int*)malloc((n + 1) * sizeof(int));
if (ST->elem == NULL) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
ST->length = n;
for (int i = 1; i <= n; i++) {
scanf("%d", &ST->elem[i]);
}
}
int Search_Seq(SSTable ST,int key) { //顺序查找
for (int i = 1; i <= ST.length; i++) {
if (ST.elem[i] == key) {
return i;
}
}
return 0;
}
int Search_Seq2(SSTable ST, int key) { //顺序查找,哨兵法
ST.elem[0] = key;
int i = ST.length;
while (ST.elem[i] != key) {
i--;
}
return i;
}
int Binary_Search(SSTable ST, int key) { //折半查找
if (ST.length == 0) return 0;
int low = 1, right = ST.length;
while (low <= right) {
int mid = (low + right) / 2;
if (ST.elem[mid] == key) return mid;
else if (ST.elem[mid] < key) low = mid + 1;
else right = mid - 1;
}
return 0;
}
int Binary_Search2(SSTable ST, int key) { //折半查找,递归法
if (ST.length == 0) return 0;
int mid = ST.length / 2;
if (ST.elem[mid] == key) return mid;
else if (ST.elem[mid] < key) {
SSTable ST2 = { ST.elem + mid + 1, ST.length - mid - 1 };
return Binary_Search2(ST2, key);
}
else {
SSTable ST2 = { ST.elem, mid };
return Binary_Search2(ST2, key);
}
}
int main() {
return 0;
}
- 分块查找
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int* data;
int length;
}SSTable;
typedef struct {
int* maxdata; //块内的最大值
int* index; //起始位置
int blocksize; //块的大小
int indexsize; //索引表的大小
}BlockTable; //索引表
int SSTabke_init(SSTable* sstable,int length) {
sstable->length = length;
sstable->data = (int*)malloc(sizeof(int) * length);
if (sstable->data == NULL) {
printf("data预分配内存失败");
return -1;
}
return 0;
}
int BlockTable_init(BlockTable* blocktable, int blocksize, int indexsize) {
blocktable->blocksize = blocksize;
blocktable->indexsize = indexsize;
blocktable->maxdata = (int*)malloc(sizeof(int) * indexsize);
if (blocktable->maxdata == NULL) {
printf("maxdata预分配内存失败\n");
return -1;
}
blocktable->index = (int*)malloc(sizeof(int) * indexsize);
if (blocktable->index == NULL) {
printf("index预分配内存失败\n");
return -1;
}
return 0;
}
//中间创建自己写
int Search_Block(SSTable* sstable, BlockTable* blocktable, int key) {
int i = 0;
for (; i < blocktable->indexsize && blocktable->maxdata[i] < key; i++); //找到第一个大于key的块
if (i == blocktable->indexsize) {
printf("没有找到\n");
return -1;
}
int j = blocktable->index[i];
for (; j < blocktable->index[i] + blocktable->blocksize; j++) {
if (sstable->data[j] == key) {
return j; //找到key
}
}
}
int main() {
return 0;
}
- 哈希查找
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 11
typedef struct {
int* data;
int length;
int capacity;
} STable;
void Init(STable* T) {
T->data = (int*)malloc(MAX_NUM * sizeof(int));
if (T->data == NULL) {
printf("内存分配失败\n");
exit(-1);
}
T->length = 0;
for (int i = 0; i < MAX_NUM; i++) {
T->data[i] = -1; // 使用-1表示空
}
T->capacity = MAX_NUM;
}
int hash_function(int key) {
return (key * 3) % 11; // 简单的哈希函数
}
//线性探测再散列
int linearProbing(STable* T, int key) {
if (T->length == MAX_NUM) {
printf("哈希表已满,无法插入新元素\n");
return -1;
}
int index = hash_function(key);
while (T->data[index] != -1) {
index = (index + 1) % MAX_NUM;
}
T->data[index] = key; // 插入元素
T->length++; // 更新表的长度
return index;
}
//二次探测再散列
int quadraticProbing(STable* T, int key) {
if (T->length == MAX_NUM) {
printf("哈希表已满,无法插入新元素\n");
return -1;
}
int index = hash_function(key);
int c = 0;
while (T->data[index] != -1) {
c++;
// 尝试正负两个方向
int plusIndex = (index + c * c) % MAX_NUM;
int minusIndex = (index - c * c + MAX_NUM) % MAX_NUM; // 确保非负
if (T->data[plusIndex] == -1) {
index = plusIndex;
}
else if (T->data[minusIndex] == -1) {
index = minusIndex;
}
else {
// 如果正负方向都已占用,继续尝试下一个c值
continue;
}
}
T->data[index] = key; // 插入元素
T->length++; // 更新表的长度
return index;
}
//随机探测再散列
int randomProbing(STable* T, int key) {
if (T->length == MAX_NUM) {
printf("哈希表已满,无法插入新元素\n");
return -1;
}
int index = hash_function(key);
int attempts = 0;
while (T->data[index] != -1) {
index = (index + rand() % MAX_NUM) % MAX_NUM;
attempts++;
if (attempts == MAX_NUM) {
printf("哈希表已满,无法插入新元素\n");
return -1;
}
}
T->data[index] = key; // 插入元素
T->length++; // 更新表的长度
return index;
}
int Hash_Search(STable* T, int key) {
int index = hash_function(key);
int start = index;
int i = 0;
while (T->data[index] != -1) {
if (T->data[index] == key)
return index;
index = (index + 1) % MAX_NUM;
if (index == start) { // 防止无限循环
break;
}
}
return -1;
}
void printHashTable(STable* T) {
printf("哈希表内容:\n");
for (int i = 0; i < MAX_NUM; i++) {
if (T->data[i] == -1) {
printf("哈希表[%d] = 空\n", i);
}
else {
printf("哈希表[%d] = %d\n", i, T->data[i]);
}
}
}
int main() {
STable T;
Init(&T);
int keys[] = { 22, 41, 53, 46, 30, 13, 1, 67 };
int n = sizeof(keys) / sizeof(keys[0]);
for (int i = 0; i < n; i++) {
linearProbing(&T, keys[i]);
}
printHashTable(&T);
int searchKey;
printf("请输入要查找的元素: ");
scanf_s("%d", &searchKey);
int index = Hash_Search(&T, searchKey);
if (index != -1) {
printf("元素 %d 在哈希表中的位置是 %d\n", searchKey, index);
}
else {
printf("哈希表中不存在元素 %d\n", searchKey);
}
// 释放内存
free(T.data);
return 0;
}
排序
- 插入类
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int* data;
int length;
int capacity;
}STable;
void InitSTable(STable* st, int capacity) {
st->data = (int*)malloc(capacity * sizeof(int));
st->length = 0;
st->capacity = capacity;
}
void CreateSTable(STable* st, int n) {
if (n > st->capacity) {
printf("Error: n exceeds capacity\n");
return;
}
st->length = n;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &st->data[i]);
}
}
void PrintSTable(STable* st) {
for (int i = 1; i <= st->length; i++) {
printf("%d ", st->data[i]);
}
printf("\n");
}
void InsertSort(STable& st) { //直接插入排序
for (int i = 2; i <= st.length; i++) {
if (st.data[i] < st.data[i - 1]) {
st.data[0] = st.data[i];
int j = i - 1;
while (j > 0 && st.data[j] > st.data[0]) {
st.data[j + 1] = st.data[j];
j--;
}
st.data[j + 1] = st.data[0];
}
}
}
void BInsertSort(STable& st) { //折半插入排序
for (int i = 2; i <= st.length; i++) {
st.data[0] = st.data[i];
int low = 1, high = i - 1, mid;
while (low < high) {
mid = (low + high) / 2;
if (st.data[mid] > st.data[0]) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
for (int j = i - 1; j >= low; j--)
st.data[j + 1] = st.data[j];
st.data[low] = st.data[0];
}
}
void ShellInsert(STable& st, int dk) { //希尔排序
for (int i = dk + 1; i <= st.length; i++) {
if (st.data[i] < st.data[i - dk]) {
st.data[0] = st.data[i];
int j;
for (j = i - dk; j > 0 && st.data[j] > st.data[0]; j -= dk) {
st.data[j + dk] = st.data[j];
}
st.data[j + dk] = st.data[0];
}
}
}
void ShellSort(STable& st, int dlta[],int t) {
for (int k = 0; k < t; k++)
ShellInsert(st, dlta[k]);
}
void TestInsertSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 5); // 输入5个整数 5 3 4 6 2
printf("InsertSort前: ");
PrintSTable(&st); // 应输出 5 3 4 6 2
InsertSort(st);
printf("InsertSort后: ");
PrintSTable(&st); // 应输出 2 3 4 5 6
}
void TestShellSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 9); // 输入9个整数 5 3 4 6 2 8 7 1 9
printf("Before ShellSort: ");
PrintSTable(&st); // 应输出 5 3 4 6 2 8 7 1 9
int dlta[] = { 5, 3, 1 }; // 增量序列
ShellSort(st, dlta, 3);
printf("After ShellSort: ");
PrintSTable(&st); // 应输出 1 2 3 4 5 6 7 8 9
}
int main() {
TestInsertSort();
TestShellSort();
return 0;
}
- 交换类
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int* data;
int length;
int capacity;
}STable;
void InitSTable(STable* st, int capacity) {
st->data = (int*)malloc(capacity * sizeof(int));
st->length = 0;
st->capacity = capacity;
}
void CreateSTable(STable* st, int n) {
if (n > st->capacity) {
printf("Error: n exceeds capacity\n");
return;
}
st->length = n;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &st->data[i]);
}
}
void PrintSTable(STable* st) {
for (int i = 1; i <= st->length; i++) {
printf("%d ", st->data[i]);
}
printf("\n");
}
void BubbleSort(STable& st) { //冒泡排序
bool exchange;
for (int i = 1; i <= st.length; i++) {
exchange = false;
for (int j = st.length; j > i; j--) {
if (st.data[j] < st.data[j-1]) {
st.data[0] = st.data[j - 1];
st.data[j - 1] = st.data[j];
st.data[j] = st.data[0];
exchange = true;
}
}
if (!exchange) break;
}
}
int Partition(STable& st,int s,int t) { //进行一次划分(快速排序)
int low = s, high = t;
st.data[0] = st.data[low];
while (low < high) {
while (low < high && st.data[high] >= st.data[0]) {
high--;
}
st.data[low] = st.data[high];
while (low < high && st.data[low] <= st.data[0]) {
low++;
}
st.data[high] = st.data[low];
}
st.data[low] = st.data[0];
return low;
}
void QuickSort(STable& st,int s,int t) {
if (s < t) {
int pivotloc = Partition(st, s, t);
QuickSort(st, s, pivotloc - 1); // 对左半部分递归排序
QuickSort(st, pivotloc + 1, t); // 对右半部分递归排序
}
}
void TestBubbleSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 5); // 输入 5 3 4 6 2(假设 data[0] 是哨兵)
printf("Before BubbleSort: ");
PrintSTable(&st); // 输出 5 3 4 6 2
BubbleSort(st);
printf("After BubbleSort: ");
PrintSTable(&st); // 应输出 2 3 4 5 6
}
void TestQuickSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 8); // 输入 4 6 1 3 8 2 5 9
printf("Before QuickSort: ");
PrintSTable(&st); // 输出 4 6 1 3 8 2 5 9
QuickSort(st, 1, st.length); // 对 data[1..length] 排序
printf("After QuickSort: ");
PrintSTable(&st); // 应输出 1 2 3 4 5 6 8 9
}
int main() {
TestBubbleSort();
TestQuickSort();
return 0;
}
- 选择类
#include<stdio.h>
#include<stdlib.h>
typedef struct {
int* data;
int length;
int capacity;
}STable;
void InitSTable(STable* st, int capacity) {
st->data = (int*)malloc(capacity * sizeof(int));
st->length = 0;
st->capacity = capacity;
}
void CreateSTable(STable* st, int n) {
if (n > st->capacity) {
printf("Error: n exceeds capacity\n");
return;
}
st->length = n;
for (int i = 1; i <= n; i++) {
scanf_s("%d", &st->data[i]);
}
}
void PrintSTable(STable* st) {
for (int i = 1; i <= st->length; i++) {
printf("%d ", st->data[i]);
}
printf("\n");
}
void SelectSort(STable& st) { //简单选择排序
for (int i = 1; i < st.length; i++) {
int k = i;
for (int j = i + 1; j <= st.length; j++)
if (st.data[j] < st.data[k])
k = j;
if (k != i) {
st.data[0] = st.data[i];
st.data[i] = st.data[k];
st.data[k] = st.data[0];
}
}
}
void HeapAdjust(STable& st, int s, int m) { //以大顶堆为例
int rc = st.data[s];
for (int j = 2 * s; j <= m; j*=2) {
if (j < m && st.data[j] < st.data[j + 1])
j++;
if (rc >= st.data[j]) break;
st.data[s] = st.data[j];
s = j;
}
st.data[s] = rc; //将rc放到合适的位置
}
void HeapSort(STable& st) { //堆排序
//建立初始堆
for (int i = st.length / 2; i >= 1; i--)
HeapAdjust(st, i, st.length);
for (int i = st.length; i > 1; i--) {
// 交换堆顶和堆底元素
st.data[0] = st.data[1];
st.data[1] = st.data[i];
st.data[i] = st.data[0];
// 调整堆
HeapAdjust(st, 1, i - 1);
}
}
void TestSelectSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 5); // 输入 5 3 4 6 2(假设 data[0] 是哨兵)
printf("Before SelectSort: ");
PrintSTable(&st); // 输出 5 3 4 6 2
SelectSort(st);
printf("After SelectSort: ");
PrintSTable(&st); // 应输出 2 3 4 5 6
}
void TestHeapSort() {
STable st;
InitSTable(&st, 10);
CreateSTable(&st, 5); // 输入 5 3 4 6 2(假设 data[0] 是哨兵)
printf("Before sorting: ");
PrintSTable(&st); // 输出 5 3 4 6 2
HeapSort(st);
printf("After sorting: ");
PrintSTable(&st); // 应输出 2 3 4 5 6
}
int main() {
TestSelectSort();
TestHeapSort();
return 0;
}
- 归并类
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int* data;
int length;
int capacity;
} STable;
void InitSTable(STable* st, int capacity) {
st->data = (int*)malloc((capacity + 1) * sizeof(int)); // 多分配一个空间给哨兵
st->length = 0;
st->capacity = capacity;
}
void CreateSTable(STable* st, int n) {
if (n > st->capacity) {
printf("Error: n exceeds capacity\n");
return;
}
st->length = n;
for (int i = 1; i <= n; i++) { // 从data[1]开始存储数据
scanf_s("%d", &st->data[i]);
}
}
void PrintSTable(STable* st) {
for (int i = 1; i <= st->length; i++) {
printf("%d ", st->data[i]);
}
printf("\n");
}
void Merge(STable* sr, STable* tr, int i, int m, int n) {
int k, j;
for (j = m + 1, k = i; i <= m && j <= n; k++) {
if (sr->data[i] <= sr->data[j])
tr->data[k] = sr->data[i++];
else
tr->data[k] = sr->data[j++];
}
while (i <= m)
tr->data[k++] = sr->data[i++];
while (j <= n)
tr->data[k++] = sr->data[j++];
}
void MergeSort(STable* sr, STable* tr, int s, int t) {
if (s < t) {
int m = (s + t) / 2;
MergeSort(sr, tr, s, m); // 排序左半部分
MergeSort(sr, tr, m + 1, t); // 排序右半部分
Merge(sr, tr, s, m, t); // 合并两个有序子序列
// 将结果复制回原数组(原地排序)
for (int k = s; k <= t; k++) {
sr->data[k] = tr->data[k];
}
}
}
void TestMergeSort() {
STable sr, tr;
InitSTable(&sr, 10);
InitSTable(&tr, 10);
printf("Input 5 numbers: ");
CreateSTable(&sr, 5); // 输入示例:5 3 4 6 2
printf("Before sorting: ");
PrintSTable(&sr); // 输出:5 3 4 6 2
tr.length = sr.length;
for (int i = 1; i <= tr.length; i++) {
tr.data[i] = 0;
}
MergeSort(&sr, &tr, 1, sr.length); // 从1开始排序
printf("After sorting: ");
PrintSTable(&sr); // 正确输出:2 3 4 5 6
free(sr.data);
free(tr.data);
}
int main() {
TestMergeSort();
return 0;
}