本次的数据结构小学期中,我的任务是完成KMP模式匹配算法、哈夫曼编码算法、由遍历序列恢复二叉树和快速排序。
要求:
1、 KMP模式匹配算法
输入:模式串,主串
功能要求:输出模式串的next值表,输出匹配结果
2、哈夫曼编码算法
输入:字符及其权值,待译码字符串,待解码字符串
功能要求:输出各字符的哈夫曼编码,输出译码字符串,输出解码字符串
3、由遍历序列恢复二叉树
输入:遍历序列
功能要求:输出二叉树形态或输出二叉树的三种遍历序列
13、快速排序
输入:待排序数据序列
功能要求:输出每步骤的枢轴选择和排序情况;希望能进行排序方向的选择(从大到小或从小到大)
直接上代码
KMP
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX = 500;
int Next[MAX];
int nextval[MAX];
typedef struct {
char ch[MAX + 1];
int length;
}SString;
int Index_KMP(SString S, SString T, int pos) {
int i = pos;
int j = 1;
while (i <= S.length && j <= T.length) {
if (j == 0 || S.ch[i] == T.ch[j]) {
++i; ++j;
}
else
j = Next[j];
}
if (j > T.length) return i - T.length;
else return 0;
}
void get_next(SString T, int Next[]) {
int i = 1;
Next[1] = 0;
int j = 0;
while (i < T.length) {
if (j == 0 || T.ch[i] == T.ch[j]) {
++i; ++j; Next[i] = j;
}
else j = Next[j];
}
}
int test1() {
SString s, t;
cout << "请输入主串s" << endl;
cin >> s.ch + 1;
s.length = strlen(s.ch + 1);
cout << "请输入子串t" << endl;
cin >> t.ch + 1;
t.length = strlen(t.ch + 1);
int m = s.length;
int n = t.length;
cout << "主串为" << endl;
for (int i = 1; i <= m; i++) {
cout << s.ch[i];
}
cout << endl;
cout << "子串为" << endl;
for (int i = 1; i <= n; i++) {
cout << t.ch[i];
}
cout << endl;
get_next(t, Next);
cout << "Next数组为" << endl;
for (int i = 1; i <= n; i++) {
cout << Next[i];
}
cout << endl;
int val = Index_KMP(s, t, 1);
if (val) cout << "在" << val << "位置匹配成功" << endl;
else cout << "匹配失败" << endl;
return 0;
}
哈夫曼编码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstring>
#include<cstdio>
#include<fstream>
#include<string>
using namespace std;
typedef struct {
int weight;
int parent, lchild, rchild;
}HTNode, * HuffmanTree;
typedef char** HuffmanCode;
int a[26 + 1], b[26 + 1];
char c[26 + 1];
void Select(HuffmanTree& HT, int n, int& s1, int& s2) {
for (int i = 1; i <= n; i++)
if (HT[i].parent == 0 && s1 == 0) { s1 = i; break; }
for (int i = 1; i <= n; i++)
if (HT[i].parent == 0 && HT[i].weight < HT[s1].weight) s1 = i;
for (int i = 1; i <= n; i++)
if (HT[i].parent == 0 && s2 == 0 && i != s1) { s2 = i; break; }
for (int i = 1; i <= n; i++)
if (HT[i].parent == 0 && HT[i].weight < HT[s2].weight && i != s1) s2 = i;
}
void CreateHuffmanTree(HuffmanTree& HT, int n) {
if (n <= 1) return;
int m = 2 * n - 1;//构造一棵哈夫曼树所需要的所有节点数
HT = new HTNode[m + 1];//m+1指从第一个结点开始,第0个结点不用
for (int i = 1; i <= m; i++) {
HT[i].parent = 0;
HT[i].lchild = 0;
HT[i].rchild = 0;
}
for (int i = 1; i <= n; i++) HT[i].weight = b[i];//把字母出现的次数赋值给哈夫曼树的weight
for (int i = n + 1; i <= m; i++) {
int s1 = 0, s2 = 0;
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;
}
}
void CreateHuffmanCode(HuffmanTree& HT, HuffmanCode& HC, int n) {
HC = new char* [n + 1];
char* cd = new char[n];
cd[n - 1] = '\0';
for (int i = 1; i <= n; i++) {
int start = n - 1, c = i, f = HT[i].parent;
while (f) {
--start;
if (HT[f].lchild == c) cd[start] = '0';
else cd[start] = '1';
c = f;
f = HT[f].parent;
}
HC[i] = new char[n - start];
strcpy(HC[i], &cd[start]);
}
delete cd;
}
int main {
freopen("SourceFile.txt", "r", stdin);//打开输入文件
memset(a, 0, sizeof(a));
string str;
getline(cin, str);//接收文件的字符串并保存到str中
for (int i = 0; i < str.length(); i++)//统计每个字母出现的频率即次数
a[str[i] - 64]++;
int n = 0;
for (int i = 1, j = 1; i <= 26; i++)//统计有多少个不同的字母以及把没出现的字母去除掉
if (a[i] != 0) {
n++;
b[j] = a[i];
c[j++] = i + 64;
}
HuffmanTree HT;
HuffmanCode HC;
CreateHuffmanTree(HT, n);
CreateHuffmanCode(HT, HC, n);
freopen("Code.txt", "w", stdout);
for (int i = 1; i <= n; i++)
cout << c[i] << ':' << HC[i] << endl;
freopen("ResultFile.txt", "w", stdout);
for (int i = 0; i < str.length(); i++) {
for (int j = 1; j <= n; j++) {
if (str[i] == c[j]) cout << HC[j];
}
}
return 0;
}
恢复二叉树
#include<stdio.h>
using namespace std;
int n;
int coo = 1;
int pre[100];
int in[100];
int back[100];
void get(int root, int start, int end)//求后序遍历结果
{
if (start > end)
return;
int i = start;
while (i < end && in[i] != pre[root]) i++;
get(root + 1, start, i - 1);
get(root + 1 + i - start, i + 1, end);
cout << pre[root] << " ";
}
void get1(int root, int start, int end)//求前序遍历结果
{
if (end < start)
return;
int i = end;
while (i > start&& in[i] != back[root]) i--;
cout << back[root] << " ";
get1(root - 1 + i - end, start, i - 1);
get1(root - 1, i + 1, end);
}
void getHou(int n) {
cout << "请输入前序遍历的结果" << endl;
memset(pre, 0, sizeof(pre));
for (int i = 0; i < n; i++)
{
cin >> pre[i];
}
cout << "请输入中序遍历的结果" << endl;
memset(in, 0, sizeof(in));
for (int i = 0; i < n; i++)
{
cin >> in[i];
}
cout << "求得后序遍历的结果为:" << endl;
get(0, 0, n - 1);
cout << endl;
}
void getQian(int n) {
memset(back, 0, sizeof(back));
memset(pre, 0, sizeof(pre));
cout << "请输入后序遍历的结果" << endl;
for (int i = 0; i < n; i++)
{
cin >> back[i];
}
cout << "请输入中序遍历的结果" << endl;
for (int i = 0; i < n; i++)
{
cin >> in[i];
}
cout << "求得前序遍历的结果为" << endl;
get1(n - 1, 0, n - 1);
}
int main()
{
cout << "请输入结点的个数" << endl;
cin >> n;
while (coo)
{
cout << "************************请选择*******************************" << endl;
cout << "************1.由前序遍历和中序遍历求后序遍历*****************" << endl;
cout << "************2.由中序遍历和后序遍历求前序遍历*****************" << endl;
cout << "************3.退出*******************************************" << endl;
cin >> coo;
switch (coo)
{
case 1:
getHou(n);
case 2:
getHou(n);
case 3:
exit(0);
default:
coo = 1;
cout << "输入错误" << endl;
break;
}
}
return 0;
}
快速排序
#pragma once
#include<iostream>
using namespace std;
#define MAXSIZE13 100
typedef int KeyType;
int p = 0, q;//全局变量,记录排序趟数和交换次数
int shu[10];
typedef struct {
KeyType key;//关键字
}Restype;
typedef struct {
Restype r[MAXSIZE13 + 1];
int length;
}SqList13;//线性表
void create(SqList13& L)
{
int i;
cout << "输入数据长度:";
cin >> L.length;
cout << "请输入数据:";
for (i = 1; i <= L.length; i++)
cin >> L.r[i].key;
}
int Partition(SqList13& L, int low, int high, int func)//确定一个线性表中枢轴位置
{
int pivotkey;
L.r[0] = L.r[low];
q++;
pivotkey = L.r[low].key;
while (low < high) {
while (low < high && (L.r[high].key >= pivotkey && func == 1 || L.r[high].key <= pivotkey && func == 2)) high--;
L.r[low] = L.r[high]; if (low != high) q++;
while (low < high && (L.r[low].key <= pivotkey && func == 1 || L.r[low].key >= pivotkey && func == 2)) low++;
L.r[high] = L.r[low]; if (low != high) q++;
}
L.r[low] = L.r[0];
q++;
return low;
}
void Qsort(SqList13& L, int low, int high, int func)//递归调用
{
int pivotloc, i, k = q;
if (low < high) {
cout << "第" << ++p << "趟排序:";
pivotloc = Partition(L, low, high, func);
for (i = 1; i <= L.length; i++)
cout << L.r[i].key << " ";
cout << ",枢轴为" << L.r[pivotloc].key;
cout << ",本次步长:" << q - k << endl;
Qsort(L, low, pivotloc - 1, func);
Qsort(L, pivotloc + 1, high, func);
}
}
void Quicksort(SqList13& L, int func)//快速排序
{
q = 0;
int j;
Qsort(L, 1, L.length, func);
}
int main()
{
SqList13 L;
int k;
cout << "快速排序" << endl << "1.递增 2.递减" << endl << "请输入操作:";
cin >> k;
create(L);
Quicksort(L, k);
cout << "总步长:" << q << endl;
return 0;
}