本次的数据结构小学期中,我的任务是完成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;
}