目录
前言
堆栈的操作
实验目的
实验要求
单链表操作
实验目的
实验要求
二叉树操作
实验目的
实验要求
查找与排序
实验目的
实验要求
查找算法
排序算法
实验总结
软件技术基础实验分为四个部分,涵盖了堆栈的操作、单链表操作、二叉树操作以及查找与排序。在课本的附录页面,提供了基础的C语言源码。鉴于本学期选修了C++,我对这些源码进行了一些修改,并补充了扩展的编程要求,且提供了一些思考题。本人因为最常使用的还是Python,所以曾经研究并手写实现过查找与排序算法,当然后面我也补充了C++版本的源码。本篇博客主要面向SWUST的同学们,旨在解释一些关键的部分,帮助大家顺利完成实验并理解其中的要点。
实验环境:Windows 11、Vistual Studio 2022、PyCharm Community Edition 2021.3.1。
- 用顺序存储结构实现栈的基本操作:Push,pop,isempty,isfull,createstack;
- 利用栈的基本操作实现conversion()函数,该函数能将任意输入的十进制整数转化为二进制形式表示。
- 扩展要求:修改程序将任意输入的十进制 修改程序将任意输入的十进制整数转化为八进制、十六进制形式表示。
#include
#include
const int maxsize = 1024;
using namespace std;
typedef int datatype;
//用于规定栈的大小和栈顶
typedef struct {
datatype elements[maxsize];
int Top;
}Stack;
//创建空栈
void setStackNull(Stack* S) {
S->Top = -1;
}
//判满
int isfull(Stack* S) {
if (S->Top >= maxsize - 1)
return 1;
else
return 0;
}
//判空
int isempty(Stack* S) {
if (S->Top < 0)
return 1;
else
return 0;
}
//压栈
void push(Stack* S, datatype E) {
if (isfull(S))
cout << "Stack Overflow" << endl;
else {
S->Top++;
S->elements[S->Top] = E;
}
}
//出栈
datatype* pop(Stack* S) {
datatype* temp;
if (isempty(S)) {
cout << "Stack Underflow" << endl;
return NULL;
}
else {
temp = (datatype*)malloc(sizeof(datatype));
*temp = S->elements[S->Top];
S->Top--;
return (temp);
}
}
//十进制整数转化为二进制数
void conversion(int n) {
Stack S;
setStackNull(&S);
int r, m;
r = n;
while (r) {
m = r % 2;
if (isfull(&S))
cout << "Over flow" << endl;
else
push(&S, m);
r = r / 2;
}
cout << "转换后的二进制为:" << endl;
while (!isempty(&S)) {
cout << *(pop(&S));
}
cout << endl;
}
void conversion2(int n, int r) {
Stack S;
int x;
setStackNull(&S);
int f = n;
while (f) {
if (isfull(&S))
cout << "Over flow" << endl;
else
push(&S, f % r);
f /= r;
}
cout << "数据" << n << "转化为" << r << "进制后的结果为:";
while (!isempty(&S)) {
x = *(pop(&S));
if (x >= 10) {
cout << (char)('A' + x - 10);
}
else {
cout << x;
}
}
cout << endl;
}
int main() {
int num;
cout << "请输入要转换为二进制的十进制数据:" << endl;
cin >> num;
conversion(num);
//扩展3功能
int n, r;
cout << "请输入转化的数字以及进制位:" << endl;
cin >> n >> r;
conversion2(n, r);
double mu;
int nu;
cout << "请输入m进制转化为n进制中m和n:" << endl;
cin >> mu >> nu;
cout << "请输入需要转换的数据:" << endl;
char arra[1024];
cin >> arra;
int s = strlen(arra);
int sum = 0;
double j = 0;
for (int i = s - 1; i >= 0; i--) {
sum += (arra[i] - '0') * pow(mu, j);
j++;
}
conversion2(sum, nu);
return 0;
}
代码实现了一个栈数据结构,并提供了一些基本的栈操作函数。栈是一种具有后进先出(LIFO)特性的数据结构,通过压栈和出栈操作实现数据的存储和检索。
具体的代码功能如下:
- 完成链表带头结点尾插入法函数。
- 完成按序号查找函数。
- 完成插入函数。
- 扩展要求:完成删除函数。
#include
using namespace std;
typedef char datatype;
struct Node {
datatype data;
Node* next;
};
typedef Node* linklist;
linklist createlist() {
char ch;
linklist head, s, r;
head = new Node();
r = head;
cout << "请输入字符生成链表,以‘#’结束" << endl;
cin.get(ch);
while (ch != '#') {
s = new Node();
s->data = ch;
r->next = s;
r = s;
cin.get(ch);
}
r->next = NULL; //链表的结束
return head; //头指针
}
linklist get(linklist head, int i) {
int j;
linklist p;
p = head;
j = 0;
while (p->next != NULL && j < i) {
p = p->next;
j++;
}
if (i == j)
return p;
else
return NULL;
}
linklist deletelink(linklist head, int i) {
linklist p = head, q;
int j = 0;
while (p ->next != NULL) {
j++;
if (j == i) {
q = p->next;
p->next = q->next;
delete q;
return head;
}
else {
p = p->next;
}
}
cout << "error" << endl;
return head;
}
void insertById(linklist head, int i, char x) {
linklist s, p;
int j;
s = new Node();
s->data = x;
p = head;
j = 0;
while (p != NULL && j < i) {
j++;
p = p->next;
}
if (p != NULL) {
s->next = p->next;
p->next = s;
}
else {
cout << "结点未找到!" << endl;
}
}
int main() {
linklist head, r;
int num;
head = createlist();
cout << "链表信息为:";
r = head->next;
while (r) {
cout << r->data;
r = r->next;
}
cout << endl;
cout << "请输入要查询的序号:" << endl;
cin >> num;
r = get(head, num);
if (r == NULL)
cout << "没有查到" << endl;
else
cout << "查找的结果为:" << r->data << endl;
cout << "请输入要删除的序号:" << endl;
int i;
cin >> i;
head = deletelink(head, i);
cout << "删除后链表信息为:";
r = head->next;
while (r) {
cout << r->data;
r = r->next;
}
cout << endl;
cout << "请输入要插入的序号和字符:" << endl;
int N;
char x;
cin >> N >> x;
insertById(head, N, x);
cout << "插入后链表信息为:";
r = head->next;
while (r) {
cout << r->data;
r = r->next;
}
return 0;
}
这段代码实现了链表的创建、查找、删除和插入等基本操作。
具体的代码功能如下:
- 编写创建如图1-1所示二叉树的函数,函数名:create。
- 编写递归实现二叉树的中序、先序和后序遍历算法。函数名分别为inorder,preorder,postorder。
- 编写主函数测试以上二叉树的创建和遍历函数。
#include
#include
using namespace std;
const int maxsize = 1024;
typedef char datatype;
typedef struct node {
datatype data;
struct node* lchild;
struct node* rchild;
} Bitree;
Bitree* CreateTree() {
char ch; //接收用户输入的节点值
Bitree* Q[maxsize]; //指针数组 Q,用于辅助构建二叉树,指针类型的数组构成队列
int front, rear; //用于指示数组 Q 的前后位置
Bitree* root, * s; //指针变量 root 和 s
root = NULL; //初始时二叉树为空
front = 1; //表示数组 Q 的初始状态
rear = 0;
cout << "请输入二叉树的各个结点,@表示虚结点,#表示结束:" << endl;
cin >> ch;
while (ch != '#') {
cout << ch;
s = NULL; //s 初始化为 NULL
if (ch != '@') {
s = (Bitree*)malloc(sizeof(Bitree));
s->data = ch; //节点值赋值给 s 的 data 成员
s->lchild = NULL;//s 的左孩子指针 lchild
s->rchild = NULL; //s 的右孩子指针 lchild
}
rear++; //rear 增加 1,并将 s 存储在 Q 数组的对应位置
Q[rear] = s;
if (rear == 1) //rear 的值为 1,即为第一个节点,将 root 指向 s
root = s;
else {
if (s && Q[front])
if (rear % 2 == 0)
Q[front]->lchild = s; //如果是偶数,则将s赋值给Q[front]节点的左孩子指针lchild
else
Q[front]->rchild = s;
if (rear % 2 == 1) //前节点是一个新的层级的节点
front++;
} //指向下一层的节点,指针 front 向下移动
cin >> ch;
}
return root; //返回二叉树的根节点指针root。
}
void preorder(Bitree* p) {
if (p != NULL) {
cout << " " << p->data << " ";
preorder(p->lchild); //以当前节点 p 的左孩子作为参数,实现前序遍历左子树。
preorder(p->rchild);
}
}
void inorder(Bitree* p) {
if (p != NULL) {
inorder(p->lchild); //当前节点 p 的左孩子作为参数,实现中序遍历左子树
cout << " " << p->data << " ";
inorder(p->rchild);
}
}
void postorder(Bitree* p) {
if (p != NULL) {
postorder(p->lchild);
postorder(p->rchild);
cout << " " << p->data << " ";
}
}
int main() {
Bitree* root;
root = CreateTree();
cout << "\n先序遍历结果如下:" << endl;
preorder(root);
cout << "\n中序遍历结果如下:" << endl;
inorder(root);
cout << "\n后序遍历结果如下:" << endl;
postorder(root);
cout << endl;
return 0;
}
这段代码实现了二叉树的基本操作。
具体的代码功能如下:
- 顺序查找:首先从键盘输入一个数据序列生成一个顺序表,然后从键盘上任意输入一个值,在顺序表中进行查找。
- 折半查找:任意输入一组数据作为各数据元素的键值,首先将此序列进行排序,然后在该有序表上使用折半查找算法进行对给定值的查找。
- 对于给定的某无序序列,分别用直接插入、希尔排序、快速排序等方法进行排序,并输出每种排序下的各趟排序结果。
基本要求是做这两个,重点还是理解折半查找。
a.顺序查找
#include
#include
using namespace std;
typedef int datatype;
typedef struct
{
vector elem;
int length;
} Stable;
void create(Stable* l)
{
cout << "请输入顺序表的内容:" << endl;
for (int i = 0; i < l->length; i++)
{
datatype data;
cout << "l.elem[" << i + 1 << "] = ";
cin >> data;
l->elem.push_back(data);
}
}
void s_search(const Stable* l, datatype k)
{
bool found = false;
for (int i = 0; i < l->length; i++)
{
if (l->elem[i] == k)
{
cout << "查找成功." << endl;
found = true;
cout << "l.elem[" << i + 1 << "] = " << k << endl;
}
}
if (!found)
{
cout << "没有找到数据" << k << "!" << endl;
}
}
int main()
{
Stable table;
datatype key;
cout << "请输入顺序表的长度: ";
cin >> table.length;
create(&table);
cout << "创建的顺序表内容:" << endl;
for (int i = 0; i < table.length; i++)
{
cout << "l.elem[" << i + 1 << "] = " << table.elem[i] << endl;
}
cout << "输入查找关键字: ";
cin >> key;
s_search(&table, key);
return 0;
}
示例:
b.折半查找
#include
using namespace std;
const int MAX = 100;
typedef struct {
int element[MAX + 1];
int length;
} Stable;
void create_seq(Stable* l)
{
cout << "请输入顺序表的内容:" << endl;
for (int i = 0; i < l->length; i++)
{
cout << "l.element[" << i + 1 << "] = ";
cin >> l->element[i];
}
}
void sort_seq(Stable* l)
{
int flag, t;
for (int i = 0; i < l->length - 1; i++)
{
flag = 0;
for (int j = 0; j < (l->length) - 1 - i; j++)
{
if (l->element[j] > l->element[j + 1])
{
t = l->element[j + 1];
l->element[j + 1] = l->element[j];
l->element[j] = t;
flag = 1;
}
}
if (flag == 0)
break;
}
}
int sea_self(const Stable* l, int k, int low, int high)
{
if (low > high)
{
cout << "没有找到查找的值" << endl;
return -1;
}
int mid = (low + high) / 2;
if (l->element[mid] == k)
{
cout << "查找成功" << endl;
cout << "l[" << mid + 1 << "] = " << k << endl;
return mid;
}
else
{
if (l->element[mid] < k)
return sea_self(l, k, mid + 1, high);
else
return sea_self(l, k, low, mid - 1);
}
}
int main()
{
Stable table;
int key;
cout << "请输入线性表的长度:";
cin >> table.length;
create_seq(&table);
sort_seq(&table);
cout << "排序后的数据" << endl;
for (int i = 0; i < table.length; i++)
{
cout << "l[" << i + 1 << "] = " << table.element[i] << endl;
}
cout << "请输入查找的值:" << endl;
cin >> key;
sea_self(&table, key, 0, table.length - 1);
return 0;
}
示例:
实现插入排序、希尔排序、快速排序。
a.Python
# 插入排序
def insert_sort(R):
for i in range(1, len(R)):
temp = R[i]
j = i - 1
while j >= 0 and temp['key'] < R[j]['key']:
R[j + 1] = R[j]
j -= 1
R[j + 1] = temp
# 希尔排序
def shell_sort(R):
n = len(R)
h = n // 2
while h > 0:
for j in range(h, n):
temp = R[j]
i = j - h
while i >= 0 and temp['key'] < R[i]['key']:
R[i + h] = R[i]
i -= h
R[i + h] = temp
h //= 2
# 快速排序
def partition(R, low, high): #用于划分数组并返回基准元素的位置。它通过交换元素的方式将小于基准的元素放在基准的左边,大于基准的元素放在基准的右边。
i = low
j = high
pivot = R[i]
while i < j:
while i < j and R[j]['key'] >= pivot['key']:
j -= 1
if i < j:
R[i] = R[j]
i += 1
while i < j and R[i]['key'] < pivot['key']:
i += 1
if i < j:
R[j] = R[i]
j -= 1
R[i] = pivot
return i
def quick_sort(R, low, high):
if low < high:
pivot_pos = partition(R, low, high)
quick_sort(R, low, pivot_pos - 1)
quick_sort(R, pivot_pos + 1, high)
if __name__ == "__main__":
# 26 5 37 1 61 11 59 15 48 19
s = 11
R = [{'key': 0} for _ in range(s)]
# 插入排序
print("请输入使用插入算法排序的10个数据,以空格分隔:")
input_str = input()
input_list = input_str.split()
for i in range(1, s):
R[i]['key'] = int(input_list[i-1])
print("插入排序之前:")
for i in range(1, s):
print(R[i]['key'], end="\t")
insert_sort(R)
print("\n插入排序之后:")
for i in range(1, s):
print(R[i]['key'], end="\t")
# 希尔排序
print("\n请输入使用希尔算法排序的10个数据,以空格分隔:")
input_str = input()
input_list = input_str.split()
for i in range(s-1):
R[i]['key'] = int(input_list[i])
print("\n希尔排序之前:")
for i in range(s-1):
print(R[i]['key'], end="\t")
shell_sort(R)
print("\n希尔排序之后:")
for i in range(s-1):
print(R[i]['key'], end="\t")
# 快速排序
print("\n请输入使用快排算法排序的10个数据,以空格分隔:")
input_str = input()
input_list = input_str.split()
for i in range(1, s):
R[i]['key'] = int(input_list[i-1])
print("\n快排排序之前:")
for i in range(1, s):
print(R[i]['key'], end="\t")
quick_sort(R, 1, s-1)
print("\n快排排序之后:")
for i in range(1, s):
print(R[i]['key'], end="\t")
示例:
b.C++
#include
#include
#include
#include
using namespace std;
const int s = 11;
typedef char datatype;
typedef struct
{
int key;
datatype others;//记录的其他域
} rectype;
/*插入排序*/
void InsertSort(rectype R[])
{
int i, j;
for (i = 2; i < s; i++)//插入的数据分别在1到n当中
{
memcpy(&R[0], &R[i], sizeof(rectype));
j = i - 1;
while (R[0].key < R[j].key)
{
R[j + 1] = R[j];//将关键字大于R[i].key 记录后移
j--;
}
R[j + 1] = R[0];
}
}
/*希尔排序*/
void ShellSort(rectype R[], int n)
{
int i, j, h;
rectype temp;
h = n / 2;
while (h > 0)
{
for (j = h; j <= n - 1; j++)
{
temp = R[j];
i = j - h;
while ((i >= 0) && temp.key < R[i].key)
{
R[i + h] = R[i];
i = i - h;
}
R[i + h] = temp;
}
h /= 2;//增量为1排序后终止算法
}
}
int Partition(rectype R[], int l, int h)
{
int i, j;
rectype temp;
i = l;
j = h;
temp = R[i];//快排第一次的基准
int flag = 1;//修改flag
while (flag)
{
while ((R[j].key >= temp.key) && (i < j))
j--;
if (i < j)
R[i++] = R[j];
while ((R[i].key < temp.key) && (i < j))
i++;
if (i < j)
R[j--] = R[i];
if (i == j)
flag = 0;
}//这段可以结合快排算法结合理解
R[i] = temp;
return i;
}
void QuickSort(rectype R[], int s1, int t1)
{
int i;
if (s1 < t1)
{
i = Partition(R, s1, t1);//对R[s1]~R[t1]作划分
QuickSort(R, s1, i - 1);
QuickSort(R, i + 1, t1);
}
}
int main()
{
// /t的含义是跳格
rectype R[s];
int i;
/*插入测试*/
cout << "请输入使用插入算法排序的10个数据" << endl;
for (i = 1; i < s; i++)
{
cin >> R[i].key;
}
cout << "插入排序之前" << endl;
for (i = 1; i < s; i++)
{
cout << R[i].key << "\t";
}
InsertSort(R);
cout << endl << "插入排序之后" << endl;
for (i = 1; i < s; i++)
{
cout << R[i].key << "\t";
}
/*希尔测试*/
cout << endl << "请输入使用希尔算法排序的10个数据" << endl;
for (i = 0; i < s - 1; i++)
{
cin >> R[i].key;
}
cout << endl << "希尔排序之前" << endl;
for (i = 0; i < s - 1; i++)
{
cout << R[i].key << "\t";
}
ShellSort(R, 10);
cout << endl << "希尔排序之后" << endl;
for (i = 0; i < s - 1; i++)
{
cout << R[i].key << "\t";
}
/*快排测试*/
cout << endl << "请输入使用快排算法排序的10个数据" << endl;
for (i = 1; i < s; i++)
{
cin >> R[i].key;
}
cout << endl << "快排排序之前" << endl;
for (i = 1; i < s; i++)
{
cout << R[i].key << "\t";
}
QuickSort(R, 1, 10);
cout << endl << "快排排序之后" << endl;
for (i = 1; i < s; i++)
{
cout << R[i].key << "\t";
}
}
示例:
祝各位同学能够顺利的完成实验,师兄先给未来的大佬们敬杯茶。