TA release HW1
This commit is contained in:
7
1/README.txt
Normal file
7
1/README.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
汇编大作业说明文档.docx 本次作业的具体内容说明
|
||||
汇编实验指导.pdf 为MIPS重点内容复习及大作业解释
|
||||
example/ “MARS环境安装与基础使用方法”部分参考代码
|
||||
exp1/ 作业“第一部分:基础练习”参考代码和样例数据
|
||||
exp2/ 作业“第二部分:实战应用”参考代码和样例数据
|
||||
attachment/ 实验用附件
|
||||
reference/ 参考文献
|
||||
BIN
1/example/example.in
Normal file
BIN
1/example/example.in
Normal file
Binary file not shown.
BIN
1/example/example.out
Normal file
BIN
1/example/example.out
Normal file
Binary file not shown.
58
1/example/example_0.asm
Normal file
58
1/example/example_0.asm
Normal file
@@ -0,0 +1,58 @@
|
||||
.data
|
||||
in_buff: .space 512
|
||||
out_buff: .space 512
|
||||
input_file: .asciiz "example.in"
|
||||
output_file: .asciiz "example.out"
|
||||
comma: .asciiz ", "
|
||||
.text
|
||||
la $a0, input_file #input_file <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a1, 0 #flag 0Ϊ<EFBFBD><EFBFBD>ȡ 1Ϊд<EFBFBD><EFBFBD>
|
||||
li $a2, 0 #mode is ignored <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0, 13 #13 Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall # <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> <EFBFBD><EFBFBD> <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>$v0<EFBFBD><EFBFBD>
|
||||
move $a0,$v0 # <EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽 $a0<EFBFBD><EFBFBD>
|
||||
la $a1, in_buff #in_buff Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a2, 512 #<EFBFBD><EFBFBD>ȡ512<EFBFBD><EFBFBD>byte
|
||||
li $v0, 14 #14 Ϊ<EFBFBD><EFBFBD>ȡ<EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
li $v0 16 #16 Ϊ<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
|
||||
#<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪN
|
||||
la $s0, in_buff
|
||||
la $s1, out_buff
|
||||
lw $s2, 0($s0)
|
||||
li $t0, 0
|
||||
|
||||
#<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD>4 ѭ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1
|
||||
for: addi $s0, $s0, 4
|
||||
addi $t0, $t0, 1
|
||||
lw $t1, 0($s0)
|
||||
sw $t1, 0($s1)
|
||||
addi $s1, $s1, 4
|
||||
#<EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
move $a0, $t1
|
||||
li $v0, 1
|
||||
syscall
|
||||
#<EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
la $a0, comma
|
||||
li $v0, 4
|
||||
syscall
|
||||
bne $t0 $s2 for
|
||||
|
||||
la $a0, output_file #output_file <EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $a1, 1 #flag 0Ϊ<EFBFBD><EFBFBD>ȡ 1Ϊд<EFBFBD><EFBFBD>
|
||||
li $a2, 0 #mode is ignored <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0<EFBFBD>Ϳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0, 13 #13 Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall # <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> <EFBFBD><EFBFBD> <EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>$v0<EFBFBD><EFBFBD>
|
||||
|
||||
move $a0,$v0 # <EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뵽 $a0<EFBFBD><EFBFBD>
|
||||
la $a1, out_buff #in_buff Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>
|
||||
sll $s2 $s2 2
|
||||
move $a2, $s2 #д<EFBFBD><EFBFBD>512<EFBFBD><EFBFBD>byte
|
||||
li $v0, 15 #15 Ϊд<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
#<EFBFBD><EFBFBD>ʱ$a0 <EFBFBD>е<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD>
|
||||
#ֱ<EFBFBD>ӵ<EFBFBD><EFBFBD><EFBFBD> syscall 16 <EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD>
|
||||
li $v0 16 #16 Ϊ<EFBFBD>ر<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD> syscall <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
syscall
|
||||
12
1/example/example_1.asm
Normal file
12
1/example/example_1.asm
Normal file
@@ -0,0 +1,12 @@
|
||||
.data
|
||||
.a
|
||||
string: .asciiz "Hello World!\n"
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0 string #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #执行系统调用
|
||||
50
1/example/example_2.asm
Normal file
50
1/example/example_2.asm
Normal file
@@ -0,0 +1,50 @@
|
||||
.data
|
||||
stringz: .asciiz "Hello World!\n"
|
||||
string: .ascii "Hello World!\n"
|
||||
#让array对齐到4byte边界
|
||||
.align 4 #没有这句话可能会出错
|
||||
array: .space 512
|
||||
#以下常数数组会自动对齐到对应边界
|
||||
barray: .byte 1,2,3,4
|
||||
harray: .half 1,2,3,4
|
||||
warray: .word 1,2,3,4
|
||||
|
||||
|
||||
.text
|
||||
main:
|
||||
la $a0 stringz #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
la $a0 string #载入字符串地址
|
||||
li $v0 4 #4代表打印字符串
|
||||
syscall #执行系统调用
|
||||
|
||||
la $t0 barray #载入byte数组地址
|
||||
lb $a0 0($t0) #读取barray[0]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 1($t0) #读取barray[1]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 2($t0) #读取barray[2]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
lb $a0 3($t0) #读取barray[3]
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
|
||||
li $a0 10 #10代表换行符'\n'
|
||||
li $v0 11 #11代表打印字符
|
||||
syscall #换个行
|
||||
|
||||
la $t0 array #载入array的地址
|
||||
li $t1 123
|
||||
sw $t1 0($t0) #在array[0]的位置存入123
|
||||
lw $a0 0($t0) #读取array[0]的数据
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #打印array[0]的数据
|
||||
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #执行系统调用
|
||||
35
1/example/example_3.asm
Normal file
35
1/example/example_3.asm
Normal file
@@ -0,0 +1,35 @@
|
||||
.text
|
||||
main:
|
||||
li $v0 5 #5代表读入一个整数
|
||||
syscall #ִ执行系统调用
|
||||
move $a0 $v0 #将读入的整数作为第一个参数
|
||||
li $v0 5 #5代表读入一个整数
|
||||
syscall #ִ执行系统调用
|
||||
move $a1 $v0 #将读入的整数作为第二个参数
|
||||
|
||||
jal product #跳转到子过程product
|
||||
move $a0 $v0 #将返回值赋值给$a0
|
||||
li $v0 1 #1代表打印一个整数
|
||||
syscall #ִ执行系统调用
|
||||
|
||||
li $v0 17 #17代表exit
|
||||
syscall #ִ执行系统调用
|
||||
|
||||
product:
|
||||
move $t0 $a0 #将第一个参数赋值给t0作为累加值
|
||||
move $t1 $a1 #将第二个参数赋值给t1作为计数器
|
||||
move $t2 $zero#结果清零
|
||||
addi $sp $sp -16 #移动栈指针到栈顶
|
||||
sw $t0 12($sp) #存入本地变量t0
|
||||
sw $t1 8($sp) #存入本地变量t1
|
||||
sw $t2 4($sp) #存入本地变量t2
|
||||
sw $ra 0($sp) #存入过程返回地址
|
||||
loop: add $t2 $t2 $t0 #结果累计t0
|
||||
sw $t2 4($sp) #存入本地变量t2
|
||||
addi $t1 $t1 -1 #计数器减一
|
||||
sw $t1 8($sp) #存入本地变量t2
|
||||
bnez $t1 loop #如果计数器不为0循环继续
|
||||
move $v0 $t2 #将结果赋给返回值
|
||||
lw $ra 0($sp) #出栈过程返回地址
|
||||
jr $ra #跳转回上一级过程
|
||||
|
||||
BIN
1/exp1/a.in
Normal file
BIN
1/exp1/a.in
Normal file
Binary file not shown.
18
1/exp1/exp1_1.cpp
Normal file
18
1/exp1/exp1_1.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
FILE *infile ,*outfile;
|
||||
int i;
|
||||
int *buffer;
|
||||
buffer = new int[2];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 2, infile);
|
||||
fclose(infile);
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, 2, outfile);
|
||||
fclose(outfile);
|
||||
scanf("%d", &i);
|
||||
i = i + 10;
|
||||
printf("%d", i);
|
||||
return 0;
|
||||
}
|
||||
12
1/exp1/exp1_2.cpp
Normal file
12
1/exp1/exp1_2.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
int i, j, temp;
|
||||
scanf("%d", &i);
|
||||
scanf("%d", &j);
|
||||
i = -i;
|
||||
if(j < 0) j = -j;
|
||||
for(temp = 0; temp < j; ++temp) i += 1;
|
||||
printf("%d",i);
|
||||
return 0;
|
||||
}
|
||||
15
1/exp1/exp1_3.cpp
Normal file
15
1/exp1/exp1_3.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
int *a, n, i, t;
|
||||
scanf("%d", &n);
|
||||
a = new int [n];
|
||||
for(i = 0; i < n; i++) scanf("%d",&a[i]);
|
||||
for(i = 0; i < n / 2; i++) {
|
||||
t = a[i] + 1;
|
||||
a[i] = a[n - i - 1] + 1;
|
||||
a[n - i - 1] = t;
|
||||
}
|
||||
for(i = 0;i < n; i++) printf("%d", a[i]);
|
||||
return 0;
|
||||
}
|
||||
18
1/exp1/exp1_4.cpp
Normal file
18
1/exp1/exp1_4.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int Hanoi(int n)
|
||||
{
|
||||
if (n == 1) { // 基准情形
|
||||
return 1;
|
||||
} else { // 递归情形
|
||||
return 2 * Hanoi(n - 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int n;
|
||||
scanf("%d", &n);
|
||||
printf("%d", Hanoi(n));
|
||||
return 0;
|
||||
}
|
||||
BIN
1/exp2/a.in
Normal file
BIN
1/exp2/a.in
Normal file
Binary file not shown.
58
1/exp2/binary_insert_sort.cpp
Normal file
58
1/exp2/binary_insert_sort.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
二分插入排序:通过二分查找找到插入位置,然后将元素插入到指定位置。
|
||||
*/
|
||||
|
||||
// 统计待排序数据的比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 递归二分查找插入位置
|
||||
int binary_search(int v[], int left, int right, int n)
|
||||
{
|
||||
if (left > right)
|
||||
return left; // 递归边界,此处不统计比较次数
|
||||
int mid = (left + right) >> 1;
|
||||
compare_count++; // 统计比较次数
|
||||
if (v[mid] > v[n])
|
||||
return binary_search(v, left, mid - 1, n);
|
||||
else
|
||||
return binary_search(v, mid + 1, right, n);
|
||||
}
|
||||
|
||||
// 将新的元素插入到指定位置,并将后续元素后移
|
||||
void insert(int *v, int k, int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= k; i--)
|
||||
{
|
||||
v[i + 1] = v[i];
|
||||
}
|
||||
v[k] = tmp;
|
||||
}
|
||||
|
||||
void binary_insertion_sort(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < n; i++)
|
||||
{ // 从第二个元素开始,依次插入到前面已经排好序的序列中
|
||||
int place = binary_search(v, 0, i - 1, i);
|
||||
insert(v, place, i);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
binary_insertion_sort(&(buffer[1]), N);
|
||||
buffer[0] = compare_count;
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, N + 1, outfile);
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
||||
59
1/exp2/insert_sort.cpp
Normal file
59
1/exp2/insert_sort.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
插入排序:将一个元素插入到一个已经排好序的序列中,使得序列依然有序。
|
||||
*/
|
||||
|
||||
// 统计比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 从后往前查找第一个比v[n]小的元素,其后一个位置即为插入位置
|
||||
int search(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
{
|
||||
compare_count++; // 统计比较次数
|
||||
if (v[i] <= tmp)
|
||||
break;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
// 将新的元素插入到指定位置,并将后续元素后移
|
||||
void insert(int *v, int k, int n)
|
||||
{
|
||||
int i;
|
||||
int tmp = v[n];
|
||||
for (i = n - 1; i >= k; i--)
|
||||
{
|
||||
v[i + 1] = v[i];
|
||||
}
|
||||
v[k] = tmp;
|
||||
}
|
||||
|
||||
void insertion_sort(int v[], int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < n; i++)
|
||||
{ // 从第二个元素开始,依次插入到前面已经排好序的序列中
|
||||
int place = search(v, i);
|
||||
insert(v, place, i);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
insertion_sort(&(buffer[1]), N);
|
||||
buffer[0] = compare_count;
|
||||
outfile = fopen("a.out", "wb");
|
||||
fwrite(buffer, 4, N + 1, outfile);
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
||||
121
1/exp2/merge_sort.cpp
Normal file
121
1/exp2/merge_sort.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "stdio.h" /*
|
||||
|
||||
链表的归并排序的核心是将链表分成前后两段,分别排序后对两个有序链表归并,递归边界是当前链表长度为1。
|
||||
*/
|
||||
|
||||
int compare_count = 0;
|
||||
|
||||
// 两个有序链表合并 , 将右链元素插入到左链中 。
|
||||
int *merge(int *l_head, int *r_head)
|
||||
{
|
||||
// 这里构建一个虚拟头结点 , 方便在第一个元素前插入 。
|
||||
int *head = new int[2];
|
||||
head[1] = (int)l_head;
|
||||
int *p_left = head;
|
||||
int *p_right = r_head;
|
||||
do
|
||||
{
|
||||
do
|
||||
{ // 寻找左链中的插入位置
|
||||
if (p_left[1] == (int)NULL)
|
||||
break;
|
||||
// count the number of comparisons
|
||||
compare_count++;
|
||||
if (((int *)p_left[1])[0] > p_right[0])
|
||||
break;
|
||||
p_left = (int *)p_left[1];
|
||||
} while (1);
|
||||
// 如果到达左链尾端 , 右链直接接上
|
||||
if (p_left[1] == (int)NULL)
|
||||
{
|
||||
p_left[1] = (int)p_right;
|
||||
break;
|
||||
}
|
||||
int *p_right_temp = p_right;
|
||||
do
|
||||
{ // 寻找右链待插入片段
|
||||
if (p_right_temp[1] == (int)NULL)
|
||||
break;
|
||||
// count the number of comparisons
|
||||
compare_count++;
|
||||
if (((int *)p_right_temp[1])[0] > ((int *)p_left[1])[0])
|
||||
break;
|
||||
p_right_temp = (int *)p_right_temp[1];
|
||||
} while (1);
|
||||
// 完成插入操作
|
||||
int *temp_right_pointer_next = (int *)p_right_temp[1];
|
||||
p_right_temp[1] = p_left[1];
|
||||
p_left[1] = (int)p_right;
|
||||
p_left = p_right_temp;
|
||||
p_right = temp_right_pointer_next;
|
||||
if (p_right == NULL)
|
||||
break;
|
||||
} while (1);
|
||||
int rv = head[1];
|
||||
|
||||
delete head;
|
||||
return (int *)rv;
|
||||
}
|
||||
|
||||
// 归并排序主函数 , 先找链表中点 , 再分别排序 , 最后归并
|
||||
int *msort(int *head)
|
||||
{
|
||||
if (head[1] == (int)NULL)
|
||||
return head;
|
||||
int *stride_2_pointer = head;
|
||||
int *stride_1_pointer = head;
|
||||
do
|
||||
{ // 通过同时进行步长为 1 和步长为 2 的跳转找中点
|
||||
if (stride_2_pointer[1] == (int)NULL)
|
||||
break;
|
||||
stride_2_pointer = (int *)stride_2_pointer[1];
|
||||
if (stride_2_pointer[1] == (int)NULL)
|
||||
break;
|
||||
stride_2_pointer = (int *)stride_2_pointer[1];
|
||||
stride_1_pointer = (int *)stride_1_pointer[1];
|
||||
} while (1);
|
||||
// 拆成两个链表分别排序 , 再归并 。
|
||||
stride_2_pointer = (int *)stride_1_pointer[1];
|
||||
stride_1_pointer[1] = (int)NULL;
|
||||
int *l_head = msort(head);
|
||||
int *r_head = msort(stride_2_pointer);
|
||||
return merge(l_head, r_head);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
// create a linked list
|
||||
int *head = new int[2];
|
||||
head[1] = (int)NULL;
|
||||
int *pointer = head;
|
||||
for (int idx = 1; idx <= N; idx++)
|
||||
{
|
||||
pointer[1] = (int)new int[2];
|
||||
pointer = (int *)pointer[1];
|
||||
pointer[0] = buffer[idx];
|
||||
pointer[1] = (int)NULL;
|
||||
}
|
||||
// sort
|
||||
head[1] = (int)msort((int *)head[1]);
|
||||
pointer = head;
|
||||
outfile = fopen("a.out", "wb");
|
||||
// 输出比较次数
|
||||
fwrite(&compare_count, 4, 1, outfile);
|
||||
// wirte the sorted list to file
|
||||
do
|
||||
{
|
||||
pointer = (int *)pointer[1];
|
||||
if (pointer == NULL)
|
||||
break;
|
||||
fwrite(pointer, 4, 1, outfile);
|
||||
} while (1);
|
||||
fclose(outfile);
|
||||
// 本文件用于翻译,没有释放链表内存的操作
|
||||
return 0;
|
||||
}
|
||||
135
1/exp2/merge_sort_runnable.cpp
Normal file
135
1/exp2/merge_sort_runnable.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "stdio.h" /*
|
||||
|
||||
链表的归并排序的核心是将链表分成前后两段,分别排序后对两个有序链表归并,递归边界是当前链表长度为1。
|
||||
|
||||
!!!注意:此代码为可运行版本,目的是让大家检验自己的实验结果是否正确
|
||||
!!!其中的链表节点是通过结构体实现的,实际汇编的实现中指针也是32位整数,请参考另一个版本的代码(merge_sort.cpp)
|
||||
|
||||
*/
|
||||
|
||||
// 统计待排序数据的比较次数
|
||||
int compare_count = 0;
|
||||
|
||||
// 链表节点, 结构体实现
|
||||
struct Node
|
||||
{
|
||||
int value;
|
||||
Node *next;
|
||||
};
|
||||
|
||||
// 两个有序链表合并,将右链元素插入到左链中 。
|
||||
Node *merge(Node *l_head, Node *r_head)
|
||||
{
|
||||
// 这里构建一个虚拟头结点,方便在第一个元素前插入。
|
||||
Node *head = new Node;
|
||||
head->next = l_head;
|
||||
Node *p_left = head;
|
||||
Node *p_right = r_head;
|
||||
do
|
||||
{
|
||||
do
|
||||
{ // 寻找左链中的插入位置
|
||||
if (p_left->next == (int)NULL)
|
||||
break;
|
||||
compare_count++; // 统计比较次数
|
||||
if ((p_left->next)->value > p_right->value)
|
||||
break;
|
||||
p_left = p_left->next;
|
||||
} while (1);
|
||||
// 如果到达左链尾端,右链直接接上
|
||||
if (p_left->next == NULL)
|
||||
{
|
||||
p_left->next = p_right;
|
||||
break;
|
||||
}
|
||||
Node *p_right_temp = p_right;
|
||||
do
|
||||
{ // 寻找右链待插入片段
|
||||
if (p_right_temp->next == NULL)
|
||||
break;
|
||||
compare_count++; // 统计比较次数
|
||||
if ((p_right_temp->next)->value > (p_left->next)->value)
|
||||
break;
|
||||
p_right_temp = p_right_temp->next;
|
||||
} while (1);
|
||||
// 完成插入操作
|
||||
Node *temp_right_pointer_next = p_right_temp->next;
|
||||
p_right_temp->next = p_left->next;
|
||||
p_left->next = p_right;
|
||||
p_left = p_right_temp;
|
||||
p_right = temp_right_pointer_next;
|
||||
if (p_right == NULL)
|
||||
break;
|
||||
} while (1);
|
||||
Node *rv = head->next;
|
||||
delete head;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// 归并排序主函数,先找链表中点,再分别排序,最后归并
|
||||
Node *msort(Node *head)
|
||||
{
|
||||
if (head->next == NULL)
|
||||
return head;
|
||||
Node *stride_2_pointer = head;
|
||||
Node *stride_1_pointer = head;
|
||||
do
|
||||
{ // 通过同时进行步长为 1 和步长为 2 的跳转找中点
|
||||
if (stride_2_pointer->next == NULL)
|
||||
break;
|
||||
stride_2_pointer = stride_2_pointer->next;
|
||||
if (stride_2_pointer->next == NULL)
|
||||
break;
|
||||
stride_2_pointer = stride_2_pointer->next;
|
||||
stride_1_pointer = stride_1_pointer->next;
|
||||
} while (1);
|
||||
// 拆成两个链表分别排序 , 再归并 。
|
||||
stride_2_pointer = stride_1_pointer->next;
|
||||
stride_1_pointer->next = NULL;
|
||||
Node *l_head = msort(head);
|
||||
Node *r_head = msort(stride_2_pointer);
|
||||
return merge(l_head, r_head);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *infile, *outfile;
|
||||
int buffer[1001];
|
||||
infile = fopen("a.in", "rb");
|
||||
fread(buffer, 4, 1001, infile);
|
||||
fclose(infile);
|
||||
int N = buffer[0];
|
||||
Node *head = new Node;
|
||||
head->next = NULL;
|
||||
Node *pointer = head;
|
||||
for (int idx = 1; idx <= N; idx++)
|
||||
{
|
||||
pointer->next = new Node;
|
||||
pointer = pointer->next;
|
||||
pointer->value = buffer[idx];
|
||||
pointer->next = NULL;
|
||||
}
|
||||
// 排序
|
||||
head->next = msort(head->next);
|
||||
// 输出到文件
|
||||
pointer = head;
|
||||
outfile = fopen("a.out", "wb");
|
||||
// 输出比较次数
|
||||
fwrite(&compare_count, 4, 1, outfile);
|
||||
do
|
||||
{
|
||||
pointer = pointer->next;
|
||||
if (pointer == NULL)
|
||||
break;
|
||||
fwrite(&(pointer->value), 4, 1, outfile);
|
||||
} while (1);
|
||||
fclose(outfile);
|
||||
// 释放链表内存
|
||||
while (head != NULL)
|
||||
{
|
||||
Node *temp = head;
|
||||
head = head->next;
|
||||
delete temp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user