1
0
mirror of https://github.com/cuntoushifu/408.git synced 2026-11-01 21:33:57 +08:00

严版教材PPT&课后答案

This commit is contained in:
杨烨
2021-12-13 17:31:41 +08:00
parent 9c54756b5e
commit 788148397f
91 changed files with 6919 additions and 2 deletions

View File

@@ -8,7 +8,7 @@
- [`DataStructure`**(数据结构)**](数据结构/)
- [x] 数据结构1800题
- [ ] 数据结构1800题分题目详解
- [x] 严版教材PPT&课后习题答案
- [x] 严版教材PPT&课后习题答案&书中算法
- [x] 王道考研数据结构PPT
- [x] 冒泡排序
- [x] 王道数据结构思维导图

View File

@@ -1,7 +1,7 @@
- [x] 数据结构1800题
- [ ] 数据结构1800题分题目详解
- [x] 王道数据结构课件
- [x] 严版教材PPT&课后习题答案
- [x] 严版教材PPT&课后习题答案&书中算法
- [x] 冒泡排序
- [x] 王道数据结构思维导图
- [x] 时间复杂度

View File

@@ -0,0 +1,171 @@
#include<iostream>
#include<fstream>
#include<string>
#include<iomanip>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
#define MAXSIZE 100 //顺序表可能达到的最大长度
struct Book {
string id;//ISBN
string name;//书名
double price;//定价
};
typedef struct {
Book *elem; //存储空间的基地址
int length; //当前长度
} SqList;
Status InitList_Sq(SqList &L) { //算法2.1 顺序表的初始化
//构造一个空的顺序表L
L.elem = new Book[MAXSIZE]; //为顺序表分配一个大小为MAXSIZE的数组空间
if (!L.elem)
exit(OVERFLOW); //存储分配失败退出
L.length = 0; //空表长度为0
return OK;
}
Status GetElem(SqList L, int i, Book &e) {//算法2.2 顺序表的取值
if (i < 1 || i > L.length)
return ERROR; //判断i值是否合理,若不合理,返回ERROR
e = L.elem[i - 1]; //elem[i-1]单元存储第i个数据元素
return OK;
}
int LocateElem_Sq(SqList L, double e) { //算法2.3 顺序表的查找
//顺序表的查找
for (int i = 0; i < L.length; i++)
if (L.elem[i].price == e)
return i + 1;//查找成功,返回序号i+1
return 0;//查找失败,返回0
}
Status ListInsert_Sq(SqList &L, int i, Book e) { //算法2.4 顺序表的插入
//在顺序表L中第i个位置之前插入新的元素e
//i值的合法范围是1<=i<=L.length+1
if ((i < 1) || (i > L.length + 1))
return ERROR; //i值不合法
if (L.length == MAXSIZE)
return ERROR; //当前存储空间已满
for (int j = L.length - 1; j >= i - 1; j--)
L.elem[j + 1] = L.elem[j]; //插入位置及之后的元素后移
L.elem[i - 1] = e; //将新元素e放入第i个位置
++L.length; //表长增1
return OK;
}
Status ListDelete_Sq(SqList &L, int i) { //算法2.5 顺序表的删除
//在顺序表L中删除第i个元素,并用e返回其值
//i值的合法范围是1<=i<=L.length
if ((i < 1) || (i > L.length))
return ERROR; //i值不合法
for (int j = i; j <= L.length; j++)
L.elem[j - 1] = L.elem[j]; //被删除元素之后的元素前移
--L.length; //表长减1
return OK;
}
int main() {
SqList L;
int i = 0, temp, a, c, choose;
double price;
Book e;
string head_1, head_2, head_3;
cout << "1. 建立\n";
cout << "2. 输入\n";
cout << "3. 取值\n";
cout << "4. 查找\n";
cout << "5. 插入\n";
cout << "6. 删除\n";
cout << "7. 输出\n";
cout << "0. 退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1://创建顺序表
if (InitList_Sq(L))
cout << "成功建立顺序表\n\n";
else
cout << "顺序表建立失败\n\n";
break;
case 2: {//顺序表信息输入
i = 0;
L.elem = new Book[MAXSIZE];
if (!L.elem)
exit(OVERFLOW);
L.length = 0;
fstream file;
file.open("book.txt");
if (!file) {
cout << "错误!未找到文件!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) {
file >> L.elem[i].id >> L.elem[i].name >> L.elem[i].price;
i++;
}
cout << "输入 book.txt 信息完毕\n\n";
L.length = i;
file.close();
}
break;
case 3://顺序表的取值
cout << "请输入一个位置用来取值:\n";
cin >> i;
temp = GetElem(L, i, e);
if (temp != 0) {
cout << "查找成功\n";
cout << "第" << i << "本图书的信息是:\n";
cout << left << setw(15) << e.id << "\t" << left << setw(50)
<< e.name << "\t" << left << setw(5) << e.price << endl
<< endl;
} else
cout << "查找失败!位置超出范围\n\n";
break;
case 4: //顺序表的查找
cout << "请输入所要查找价格:";
cin >> price;
temp = LocateElem_Sq(L, price);
if (temp != 0) {
cout << "查找成功\n";
cout << "该价格对应的书名为:" << L.elem[temp - 1].name << endl << endl;
} else
cout << "查找失败!没有这个价格对应的书籍\n\n";
break;
case 5: //顺序表的插入
cout << "请输入插入的位置和书本信息,包括:编号 书名 价格(用空格隔开):";
cin >> a;
cin >> e.id >> e.name >> e.price; //输入a和b,a代表插入的位置,b代表插入的数值(书本信息)
if (ListInsert_Sq(L, a, e))
cout << "插入成功.\n\n";
else
cout << "插入失败.\n\n";
break;
case 6: //顺序表的删除
cout << "请输入所要删除的书籍的位置:";
cin >> c;
if (ListDelete_Sq(L, c))
cout << "删除成功.\n\n";
else
cout << "删除失败.\n\n";
break;
case 7: //顺序表的输出
cout << "当前图书系统信息(顺序表)读出:\n";
for (i = 0; i < L.length; i++)
cout << left << setw(15) << L.elem[i].id << "\t" << left
<< setw(50) << L.elem[i].name << "\t" << left
<< setw(5) << L.elem[i].price << endl;
cout << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,17 @@
ISBN 书名 定价
9787302257646 程序设计基础 25
9787302219972 单片机技术及应用 32
9787302203513 编译原理 46
9787811234923 汇编语言程序设计教程 21
9787512100831 计算机操作系统 17
9787302265436 计算机导论实验指导 18
9787302180630 实用数据结构 29
9787302225065 数据结构(C语言版) 38
9787302171676 C#面向对象程序设计 39
9787302250692 C语言程序设计 42
9787302150664 数据库原理 35
9787302260806 Java编程与实践 56
9787302252887 Java程序设计与应用教程 39
9787302198505 嵌入式操作系统及编程 25
9787302169666 软件测试 24
9787811231557 Eclipse基础与应用 35

View File

@@ -0,0 +1,189 @@
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
struct Book {
string id;//ISBN
string name;//书名
double price;//定价
};
typedef struct DuLNode {
Book data; //数据域
struct DuLNode *prior; //直接前驱
struct DuLNode *next; //直接后继
} DuLNode, *DuLinkList;
string head_1, head_2, head_3;
int length;
Status InitDuList_L(DuLinkList &L) {
//构造一个空的双向链表L
L = new DuLNode; //生成新结点作为头结点,用头指针L指向头结点
L->next = NULL; //头结点的指针域置空
L->prior = NULL;
return OK;
}
DuLNode *GetElemP_DuL(DuLinkList L, int i) {
//在带头结点的双向链表L中查找第i个元素,返回结点的地址
int j;
DuLinkList p;
p = L->next;
j = 1; //初始化,p指向第一个结点,j为计数器
while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
p = p->next;
++j;
}
if (!p || j > i)
return NULL; //第i个元素不存在
return p;
} //GetElemP_DuL
Status ListInsert_DuL(DuLinkList &L, int i, Book e) { //算法2.13 双向链表的插入
//在带头结点的双向链表L中第i个位置之前插入元素e,i的合法值为1<=i<=表长+1
DuLinkList s, p;
if (!(p = GetElemP_DuL(L, i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
if (i == 1) {//在双向链表的第一个元素上插入
s = new DuLNode; //生成新结点s
s->data = e; //将结点s数据置为e
DuLinkList p = L->next;
L->next = s;
s->prior = L;
s->next = p;//将结点*s插入L中
p->prior = s;
++length;
} else if (i == length) {//在双向链表的最后一个元素上插入
s = new DuLNode; //生成新结点s
s->data = e; //将结点s数据置为e
DuLinkList p = L;
while (p->next)
p = p->next;//将LinkList p指向双向链表结尾
p->next = s;
s->prior = p;//将结点*s插入到p的后面,插入到L中
s->next = NULL;
++length;
} else {
s = new DuLNode; //生成新结点*s
s->data = e; //将结点*s数据域置为e
s->prior = p->prior; //将结点*s插入L中,此步对应图2.20①
p->prior->next = s; //对应图2.20②
s->next = p; //对应图2.20③
p->prior = s; //对应图2.20④
++length;
}
return OK;
} //ListInsert_DuL
Status ListDelete_DuL(DuLinkList &L, int i) { //算法2.14 双向链表的删除
//删除带头结点的双向链表L中第i个位置之前插入元素e,i的合法值为1<=i<=表长
DuLinkList p;
if (!(p = GetElemP_DuL(L, i))) //在L中确定第i个元素的位置指针p
return ERROR; //p为NULL时,第i个元素不存在
if (i == 1)//删除双向链表的第一个元素
L = L->next;
else if (i == length) {//删除双向链表的最后一个元素
p->prior->next = NULL;
delete p;
--length;
return OK;
} else {
p->prior->next = p->next; //修改被删结点的前驱结点的后继指针,对应图2.21①
p->next->prior = p->prior; //修改被删结点的后继结点的前驱指针,对应图2.21②
delete p; //释放被删结点的空间
--length;
return OK;
}
}//ListDelete_DuL
void CreateDuList_L(DuLinkList &L) {
//正位序输入n个元素的值,建立带表头结点的双向链表L,同时建立前驱指针
DuLinkList r, p;
L = new DuLNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L;//尾指针r指向头结点
length = 0;
fstream file;
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) {
p = new DuLNode; //生成新结点
file >> p->data.id >> p->data.name >> p->data.price; //输入元素值
p->next = NULL;
r->next = p; //插入到表尾
r = p; //r指向新的尾结点
p->prior = L->prior; //插入到表头
L->prior = p;
length++;
}
file.close();
} //CreateDuList_L
int main() {
int a, choose;
Book e;
DuLinkList L, p;
cout << "1. 建立\n";
cout << "2. 输入\n";
cout << "3. 插入\n";
cout << "4. 删除\n";
cout << "5. 输出\n";
cout << "0. 退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1: //建立一个双向链表
if (InitDuList_L(L))
cout << "成功建立双向链表!\n\n";
break;
case 2: //使用后插法创建双向链表
CreateDuList_L(L);
cout << "输入 book.txt 信息完毕\n\n";
break;
case 3: //双向链表的插入
cout << "请输入两个数分别代表插入的位置和数值(书的信息:编号&书名&价格):";
cin >> a;
cin >> e.id >> e.name >> e.price;
if (ListInsert_DuL(L, a, e))
cout << "插入成功.\n\n";
else
cout << "插入失败!\n\n";
break;
case 4: //双向链表的删除
cout << "请输入所要删除的书籍的位置:";
cin >> a;
if (ListDelete_DuL(L, a))
cout << "删除成功!\n\n";
else
cout << "删除失败!\n\n";
break;
case 5: //双向链表的输出
cout << "当前图书系统信息读出:\n";
p = L->next;
while (p) {
cout << left << setw(15) << p->data.id << "\t" << left << setw(
50) << p->data.name << "\t" << left << setw(5)
<< p->data.price << endl;
p = p->next;
}
cout << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,17 @@
ISBN 书名 定价
9787302257646 程序设计基础 25
9787302219972 单片机技术及应用 32
9787302203513 编译原理 46
9787811234923 汇编语言程序设计教程 21
9787512100831 计算机操作系统 17
9787302265436 计算机导论实验指导 18
9787302180630 实用数据结构 29
9787302225065 数据结构(C语言版) 38
9787302171676 C#面向对象程序设计 39
9787302250692 C语言程序设计 42
9787302150664 数据库原理 35
9787302260806 Java编程与实践 56
9787302252887 Java程序设计与应用教程 39
9787302198505 嵌入式操作系统及编程 25
9787302169666 软件测试 24
9787811231557 Eclipse基础与应用 35

View File

@@ -0,0 +1,109 @@
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#define ERROR 0
typedef struct LNode {
int data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *List; //LinkList为指向结构体LNode的指针类型
int n, m;
char st = 'A';
void InitList(List &L) //创建链表
{
L = new LNode;
L->next = NULL;
}
void ListInput(List &L, int n) //链表数据的输入
{
int i;
List p, r;
r = L;
char filename[20] = { 0 };
cout << "请输入顺序表L" << st << "的数据文件名称(文件名+“.txt”,如List" << st << ".txt):" << endl;
++st;
gets(filename);
fstream file;
file.open(filename);
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
while (!file.eof()) {
p = new LNode;
file >> p->data;
p->next = NULL;
r->next = p;
r = p;
n++;
}
file.close();
}
bool LocateElem(List L, int e) //判断List里有没有e这个元素
{
List p;
p = L->next;
while (p != NULL) {
if (p->data == e)
return true;
p = p->next;
}
return false;
}
void ListInsert(List &L, int e) //将e插入到List中
{
List p;
p = new LNode;
p->data = e;
p->next = L->next;
L->next = p;
}
void ListOutput(List L) //输出List
{
List p;
p = L->next;
while (p != NULL) {
cout << p->data << " ";
p = p->next;
}
cout << endl;
}
void unionList(List &LA, List LB) //算法2.15 线性表的合并(链表)
{
//将所有在线性表LB中但不在LA中的数据元素插入到LA中
int e;
List p;
p = LB->next;
while (p != NULL) {
e = p->data;
if (!LocateElem(LA, e)) //LA中不存在和e相同的数据元素,则插入之
ListInsert(LA, e);
p = p->next;
}
} //unionList
int main() {
List LA, LB;
InitList(LA);
InitList(LB);
ListInput(LA, n);
ListInput(LB, m);
unionList(LA, LB);
cout << "LA和LB合并后的集合为:\n";
ListOutput(LA);
return 0;
}

View File

@@ -0,0 +1,100 @@
#include<iostream>
#include<fstream>
using namespace std;
#define MAXSIZE 100
#define ERROR 0
typedef struct { //定义顺序表
int *elem;
int length;
} List;
int n, m;
char st = 'A';
void InitList(List &L) //创建顺序表
{
L.elem = new int[MAXSIZE];
L.length = 0;
}
void ListInput(List &L, int n) //顺序表数据的输入
{
int i = 0;
char filename[20] = { 0 };
cout << "请输入顺序表L" << st << "的数据文件名称(文件名+“.txt”,如List" << st << ".txt):" << endl;
++st;
gets(filename);
fstream file;
file.open(filename);
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
while (!file.eof()) {
file >> L.elem[i];
i++;
}
L.length = i;
}
int ListLength(List L) //求顺序表的长度
{
return L.length;
}
void GetElem(List L, int i, int &e) //求顺序表的第i个元素,并以e返回
{
e = L.elem[i - 1];
}
bool LocateElem(List L, int e) //判断List里有没有e这个元素
{
int i;
for (i = 0; i < L.length; i++)
if (e == L.elem[i])
return true;
return false;
}
void ListInsert(List &L, int e) //将e插入到List的最后
{
L.elem[L.length] = e;
L.length++;
}
void ListOutput(List L) //输出List
{
int i;
for (i = 0; i < L.length; i++)
cout << L.elem[i] << " ";
cout << endl;
}
void unionList(List &LA, List LB) //算法2.14 线性表的合并(顺序表)
{
//将所有在线性表LB中但不在LA中的数据元素插入到LA中
int LA_len, LB_len, i, e;
LA_len = ListLength(LA);
LB_len = ListLength(LB); //求线性表的长度
for (i = 1; i <= LB_len; i++) {
GetElem(LB, i, e); //取LB中第i个数据元素赋给e
if (!LocateElem(LA, e)) //LA中不存在和e相同的数据元素,则插入之
ListInsert(LA, e);
}
} //unionList
int main() {
List LA, LB;
InitList(LA);
InitList(LB);
ListInput(LA, n);
ListInput(LB, m);
unionList(LA, LB);
cout << "LA和LB合并后的集合为:\n";
ListOutput(LA);
return 0;
}

View File

@@ -0,0 +1,93 @@
#include<iostream>
#include<fstream>
using namespace std;
#define MAXSIZE 100
#define ERROR 0
typedef struct //定义顺序表
{
int *elem;
int length;
} SqList;
int num_a = 0, num_b = 0;
char st = 'A';
void InitList_Sq(SqList &L, int n) //创建顺序表
{
L.elem = new int[MAXSIZE];
if (!L.elem)
exit(0);
L.length = 0;
}
void input(SqList &L, int n) //依次往顺序表L里输入数据
{
int i = 0;
char filename[20] = { 0 };
cout << "请输入非递减线性表" << st << "的数据文件名称(文件名+“.txt”,如List" << st << ".txt):" << endl;
++st;
gets(filename);
fstream file;
file.open(filename);
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
while (!file.eof()) {
file >> L.elem[i];
i++;
}
L.length = i;
}
void output(SqList L) //依次输出顺序表里的每个元素
{
int i;
for (i = 0; i < L.length; i++) {
if (i)
cout << ",";
cout << L.elem[i];
}
}
void MergeList_Sq(SqList LA, SqList LB, SqList &LC) //算法2.16 顺序有序表的合并
{
//已知顺序有序表LA和LB的元素按值非递减排列
//归并LA和LB得到新的顺序有序表LC,LC的元素也按值非递减排列
int *pa, *pb, *pc, *pa_last, *pb_last;
pa = LA.elem;
pb = LB.elem; //指针pa和pb的初值分别指向两个表的第一次元素
LC.length = LA.length + LB.length; //新表长度为待合并两表的长度之和
LC.elem = new int[LC.length]; //为合并后的新表分配一个数组空间
pc = LC.elem; //指针pc指向新表的第一个元素
pa_last = LA.elem + LA.length - 1; //指针pa_last指向LA表的最后一个元素
pb_last = LB.elem + LB.length - 1; //指针pb_last指向LB表的最后一个元素
while (pa <= pa_last && pb <= pb_last) //两个表都非空
{
if (*pa <= *pb) //依次“摘取”两表中值较小的结点插入到LC表的最后
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while (pa <= pa_last) //LB已到达表尾,依次将LA的剩余元素插入LC表的最后
*pc++ = *pa++;
while (pb <= pb_last) //LA已到达表尾,依次将LB的剩余元素插入LC表的最后
*pc++ = *pb++;
} //MergeList_List
int main() {
SqList La, Lb, Lc;
InitList_Sq(La, num_a); //La表的创建
input(La, num_a); //依次往顺序表La里输入数据
InitList_Sq(Lb, num_b); //Lb表的创建
input(Lb, num_b); //依次往顺序表La里输入数据
MergeList_Sq(La, Lb, Lc); //将顺序表La和Lb进行合并
cout << "非递减线性表A,B合并后的非递减线性表C为:\n"; //输出合并后的有序顺序表Lc
output(Lc);
cout << endl;
return 0;
}

View File

@@ -0,0 +1,104 @@
#include<iostream>
#include<fstream>
using namespace std;
#define ERROR 0
typedef struct LNode //定义单链表
{
int data;
struct LNode *next;
} LNode, *LinkList;
int num_a, num_b;
char st = 'A';
void InitList_L(LinkList &L) //创建单链表
{
L = new LNode;
L->next = NULL;
}
void input(LinkList &L, int n) //依次往单链表L里输入数据
{
int i;
LNode *p, *r;
r = L;
char filename[20] = { 0 };
cout << "请输入非递减单链表" << st << "的数据文件名称(文件名+“.txt”,如List" << st << ".txt):" << endl;
++st;
gets(filename);
fstream file;
file.open(filename);
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
while (!file.eof()) {
p = new LNode;
file >> p->data;
p->next = NULL;
r->next = p;
r = p;
n++;
}
file.close();
}
void output(LinkList L) //依次输出单链表里的每个元素
{
int i = 0;
LNode *p;
p = L->next;
while (p) {
if (i)
cout << ",";
cout << p->data;
p = p->next;
i = 1;
}
}
void MergeList_L(LinkList &LA, LinkList &LB, LinkList &LC) //算法2.17 链式有序表的合并
{
//已知单链表LA和LB的元素按值非递减排列
//归并LA和LB得到新的单链表LC,LC的元素也按值非递减排列
LinkList pa, pb, pc;
pa = LA->next;
pb = LB->next; //pa和pb的初值分别指向两个表的第一个结点
LC = LA; //用LA的头结点作为LC的头结点
pc = LC; //pc的初值指向LC的头结点
while (pa && pb) //两个表都非空
{
if (pa->data <= pb->data) //依次"摘取"两表中值较小的结点插入到LC表的最后
{
pc->next = pa; //将pa所指结点链接到pc所指结点之后
pc = pa;
pa = pa->next;
} else {
pc->next = pb; //将pb所指结点链接到pc所指结点之后
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb; //插入非空表的剩余段
delete LB; //释放LB的头结点
} //MergeList_L()
int main() {
LinkList La, Lb, Lc;
InitList_L(La); //La表的创建
input(La, num_a); //依次往单链表La里输入数据
InitList_L(Lb); //Lb表的创建
input(Lb, num_b); //依次往单链表La里输入数据
InitList_L(Lc);
MergeList_L(La, Lb, Lc); //将单链表La和Lb进行合并
cout << "非递减单链表A,B合并后的非递减单链表C为:\n"; //输出合并后的单链表Lc
output(Lc);
cout << endl;
return 0;
}

View File

@@ -0,0 +1,124 @@
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
#define ERROR 0
typedef struct PNode {
float coef; //系数
int expn; //指数
struct PNode *next;
} PNode, *Polynomial;
string head_1, head_2;
int temp;
char st = 'A';
void CreatPolyn(Polynomial &P, int m) //算法2.18 多项式的创建
{
//输入m项的系数和指数,建立表示一个多项式的有序链表P
Polynomial q, pre, s;
int i;
P = new PNode;
P->next = NULL; //先建立一个带头结点的单链表
char filename[20] = { 0 };
cout << "请输入有关多项式p" << char(st + 32) << "系数和指数的数据文件名称(文件名+“.txt”,如Poly" << st << ".txt):" << endl;
++st;
gets(filename);
fstream file;
file.open(filename);
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2;
while (!file.eof())
{
s = new PNode; //生成新结点
file >> s->coef >> s->expn; //输入元素值
pre = P; //pre用于保存q的前驱,初值为头结点
q = P->next;
while (q && q->expn < s->expn) //通过比较指数找到第一个大于输入项指数的项q
{
pre = q;
q = q->next;
} //while
s->next = q; //将输入项s插入到q和其前驱结点pre之间
pre->next = s;
}//for
file.close();
} //CreatPolyn
void AddPolyn(Polynomial &Pa, Polynomial &Pb) //算法2.19 多项式的相加
{
//多项式加法:Pa=Pa+Pb,利用两个多项式的结点构成“和多项式”
Polynomial r, p1, p2, p3;
float sum;
p1 = Pa->next;
p2 = Pb->next; //p1和p2初值分别指向Pa和Pb的第一个结点
p3 = Pa; //p3指向和多项式的当前结点,初值为Pa
while (p1 && p2) //p1和p2均非空
{
if (p1->expn == p2->expn) //指数相等
{
sum = p1->coef + p2->coef; //sum保存两项的系数和
if (sum != 0) //系数和不为0
{
p1->coef = sum; //修改Pa当前结点p1的系数值为两项系数的和
p3->next = p1;
p3 = p1; //将修改后的Pa当前结点p1链在p3之后,p3指向p1
p1 = p1->next; //p1指向后一项
r = p2;
p2 = p2->next;
delete r; //删除Pb当前结点r
} else //系数和为0
{
r = p1;
p1 = p1->next;
delete r; //删除Pb当前结点p1
r = p2;
p2 = p2->next;
delete r; //删除Pb当前结点p2
}
} else if (p1->expn < p2->expn) //Pa当前结点p1的指数值小
{
p3->next = p1; //将p1链在p3之后
p3 = p1; //p3指向p1
p1 = p1->next; //p1指向后一项
} else //Pa当前结点p2的指数值小
{
p3->next = p2; //将p2链在p3之后
p3 = p2; //p3指向p2
p2 = p2->next; //p2指向后一项
}
} //while
p3->next = p1 ? p1 : p2; //插入非空多项式的剩余段
delete Pb; //释放Pb的头结点
} //AddPolyn
int main() {
Polynomial Pa, Pb;
Polynomial p;
int i;
//创建多项式Pa
CreatPolyn(Pa, temp); //调用函数,输入Pa每一项的系数和指数
//创建多项式Pb
CreatPolyn(Pb, temp); //调用函数,输入Pa每一项的系数和指数
AddPolyn(Pa, Pb);
cout << "多项式Pa和Pb相加后的结果是:\n";
p = Pa->next;
i = 0;
while (p) //输出相加后的结果,每一项以x^n表示
{
if (i)
cout << " + ";
cout << "(" << p->coef << ") * x^" << p->expn;
p = p->next;
i = 1;
}
cout << endl;
return 0;
}

View File

@@ -0,0 +1,5 @@
系数p 指数
7 0
3 1
9 8
5 17

View File

@@ -0,0 +1,4 @@
系数p 指数
8 1
22 7
-9 8

View File

@@ -0,0 +1,227 @@
#include<iostream>
#include<string>
#include<iomanip>
#include<fstream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status; //Status 是函数返回值类型,其值是函数结果状态代码。
typedef int ElemType; //ElemType 为可定义的数据类型,此设为int类型
struct Book {
string id;//ISBN
string name;//书名
double price;//定价
};
typedef struct LNode {
Book data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
string head_1, head_2, head_3;
int length;
Status InitList_L(LinkList &L) { //算法2.6 单链表的初始化
//构造一个空的单链表L
L = new LNode; //生成新结点作为头结点,用头指针L指向头结点
L->next = NULL; //头结点的指针域置空
return OK;
}
Status GetElem_L(LinkList L, int i, Book &e) { //算法2.7 单链表的取值
//在带头结点的单链表L中查找第i个元素
//用e返回L中第i个数据元素的值
int j;
LinkList p;
p = L->next;
j = 1; //初始化,p指向第一个结点,j为计数器
while (j < i && p) { //顺链域向后扫描,直到p指向第i个元素或p为空
p = p->next; //p指向下一个结点
++j; //计数器j相应加1
}
if (!p || j > i)
return ERROR; //i值不合法i>n或i<=0
e = p->data; //取第i个结点的数据域
return OK;
} //GetElem_L
LNode *LocateElem_L(LinkList L, int e) { //算法2.8 按值查找
//在带头结点的单链表L中查找值为e的元素
LinkList p;
p = L->next;
while (p && p->data.price != e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
p = p->next; //p指向下一个结点
return p; //查找成功返回值为e的结点地址p,查找失败p为NULL
} //LocateElem_L
Status ListInsert_L(LinkList &L, int i, Book &e) { //算法2.9 单链表的插入
//在带头结点的单链表L中第i个位置插入值为e的新结点
int j;
LinkList p, s;
p = L;
j = 0;
while (p && j < i - 1) {
p = p->next;
++j;
}//查找第i?1个结点,p指向该结点
if (!p || j > i - 1)
return ERROR; //i>n+1或者i<1
s = new LNode; //生成新结点*s
s->data = e; //将结点*s的数据域置为e
s->next = p->next; //将结点*s的指针域指向结点ai
p->next = s; //将结点*p的指针域指向结点*s
++length;
return OK;
} //ListInsert_L
Status ListDelete_L(LinkList &L, int i) { //算法2.9 单链表的删除
//在带头结点的单链表L中,删除第i个位置
LinkList p, q;
int j;
p = L;
j = 0;
while ((p->next) && (j < i - 1)) //查找第i?1个结点,p指向该结点
{
p = p->next;
++j;
}
if (!(p->next) || (j > i - 1))
return ERROR; //当i>n或i<1时,删除位置不合理
q = p->next; //临时保存被删结点的地址以备释放
p->next = q->next; //改变删除结点前驱结点的指针域
delete q; //释放删除结点的空间
--length;
return OK;
} //ListDelete_L
void CreateList_H(LinkList &L, int n) { //算法2.11 前插法创建单链表
//逆位序输入n个元素的值,建立到头结点的单链表L
LinkList p;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
length = 0;
fstream file;
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) {
p = new LNode; //生成新结点*p
file >> p->data.id >> p->data.name >> p->data.price; //输入元素值赋给新结点*p的数据域
p->next = L->next;
L->next = p; //将新结点*p插入到头结点之后
length++;//同时对链表长度进行统计
}
file.close();
} //CreateList_F
void CreateList_R(LinkList &L, int n) { //算法2.12 后插法创建单链表
//正位序输入n个元素的值,建立带表头结点的单链表L
LinkList p, r;
L = new LNode;
L->next = NULL; //先建立一个带头结点的空链表
r = L; //尾指针r指向头结点
length = 0;
fstream file; //打开文件进行读写操作
file.open("book.txt");
if (!file) {
cout << "未找到相关文件,无法打开!" << endl;
exit(ERROR);
}
file >> head_1 >> head_2 >> head_3;
while (!file.eof()) { //将文件中的信息运用后插法插入到链表中
p = new LNode;//生成新结点
file >> p->data.id >> p->data.name >> p->data.price;//输入元素值赋给新结点*p的数据域
p->next = NULL;
r->next = p;//将新结点*p插入尾结点*r之后
r = p;//r指向新的尾结点*p
length++; //同时对链表长度进行统计
}
file.close();
} //CreateList_L
int main() {
int a, n, choose;
double price;
Book e;
LinkList L, p;
cout << "1. 建立\n";
cout << "2. 输入\n";
cout << "3. 取值\n";
cout << "4. 查找\n";
cout << "5. 插入\n";
cout << "6. 删除\n";
cout << "7. 输出\n";
cout << "0. 退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1: //建立一个单链表
if (InitList_L(L))
cout << "成功建立链表!\n\n";
break;
case 2: //使用后插法创建单链表
CreateList_R(L, length);
cout << "输入 book.txt 信息完毕\n\n";
break;
case 3: //单链表的按序号取值
cout << "请输入一个位置用来取值:";
cin >> a;
if (GetElem_L(L, a, e)) {
cout << "查找成功\n";
cout << "第" << a << "本图书的信息是:\n";
cout << left << setw(15) << e.id << "\t" << left << setw(50)
<< e.name << "\t" << left << setw(5) << e.price << endl
<< endl;
} else
cout << "查找失败\n\n";
break;
case 4: //单链表的按值查找
cout << "请输入所要查找价格:";
cin >> price;
if (LocateElem_L(L, price) != NULL) {
cout << "查找成功\n";
cout << "该价格对应的书名为:" << LocateElem_L(L, price)->data.name
<< endl << endl;
} else
cout << "查找失败! 定价" << price << " 没有找到\n\n";
break;
case 5: //单链表的插入
cout << "请输入插入的位置和书的信息,包括:编号 书名 价格(用空格隔开):";
cin >> a;
cin >> e.id >> e.name >> e.price;
if (ListInsert_L(L, a, e))
cout << "插入成功.\n\n";
else
cout << "插入失败!\n\n";
break;
case 6: //单链表的删除
cout << "请输入所要删除的书籍的位置:";
cin >> a;
if (ListDelete_L(L, a))
cout << "删除成功!\n\n";
else
cout << "删除失败!\n\n";
break;
case 7: //单链表的输出
cout << "当前图书系统信息(链表)读出:\n";
p = L->next;
while (p) {
cout << left << setw(15) << p->data.id << "\t" << left << setw(
50) << p->data.name << "\t" << left << setw(5)
<< p->data.price << endl;
p = p->next;
}
cout << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,17 @@
ISBN 书名 定价
9787302257646 程序设计基础 25
9787302219972 单片机技术及应用 32
9787302203513 编译原理 46
9787811234923 汇编语言程序设计教程 21
9787512100831 计算机操作系统 17
9787302265436 计算机导论实验指导 18
9787302180630 实用数据结构 29
9787302225065 数据结构(C语言版) 38
9787302171676 C#面向对象程序设计 39
9787302250692 C语言程序设计 42
9787302150664 数据库原理 35
9787302260806 Java编程与实践 56
9787302252887 Java程序设计与应用教程 39
9787302198505 嵌入式操作系统及编程 25
9787302169666 软件测试 24
9787811231557 Eclipse基础与应用 35

View File

@@ -0,0 +1,117 @@
/***顺序栈的实现***/
#include<iostream>
#include<fstream>
using namespace std;
//顺序栈定义
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100//顺序栈存储空间的初始分配量
typedef int Status;
typedef char SElemType;
typedef struct {
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用的最大容量
} SqStack;
//算法3.1 顺序栈的初始化
Status InitStack(SqStack &S) {
//构造一个空栈S
S.base = new SElemType[MAXSIZE];//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
if (!S.base)
exit(OVERFLOW); //存储分配失败
S.top = S.base; //top初始为base,空栈
S.stacksize = MAXSIZE; //stacksize置为栈的最大容量MAXSIZE
return OK;
}
//算法3.2 顺序栈的入栈
Status Push(SqStack &S, SElemType e) {
// 插入元素e为新的栈顶元素
if (S.top - S.base == S.stacksize)
return ERROR; //栈满
*(S.top++) = e; //元素e压入栈顶,栈顶指针加1
return OK;
}
//算法3.3 顺序栈的出栈
Status Pop(SqStack &S, SElemType &e) {
//删除S的栈顶元素,用e返回其值
if (S.base == S.top)
return ERROR;//栈空
e = *(--S.top); //栈顶指针减1,将栈顶元素赋给e
return OK;
}
//算法3.4 取顺序栈的栈顶元素
char GetTop(SqStack S) {//返回S的栈顶元素,不修改栈顶指针
if (S.top != S.base) //栈非空
return *(S.top - 1); //返回栈顶元素的值,栈顶指针不变
}
int main() {
SqStack s;
int choose, flag = 0;
SElemType j, e, t;
cout << "1.初始化\n";
cout << "2.入栈\n";
cout << "3.读栈顶元素\n";
cout << "4.出栈\n";
cout << "0.退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1://算法3.1 顺序栈的初始化
if (InitStack(s)) {
flag = 1;
cout << "成功对栈进行初始化\n\n";
} else
cout << "初始化栈失败\n\n";
break;
case 2: {//算法3.2 顺序栈的入栈
fstream file;
file.open("SqStack.txt");//
if (!file) {
cout << "错误!未找到文件!\n\n" << endl;
exit(ERROR);
}
if (flag) {
flag = 1;
cout << "进栈元素依次为:\n";
while (!file.eof()) {
file >> j;
if (file.fail())
break;
else {
Push(s, j);
cout << j << " ";
}
}
cout << endl << endl;
} else
cout << "栈未建立,请重新选择\n\n";
file.close();
}
break;
case 3://算法3.3 顺序栈的出栈
if(flag != -1 && flag != 0)
cout << "栈顶元素为:\n" << GetTop(s) << endl << endl;
else
cout << "栈中无元素,请重新选择\n" << endl;
break;
case 4://算法3.4 取顺序栈的栈顶元素
cout << "依次弹出的栈顶元素为:\n";
while (Pop(s, t)){
flag = -1;
cout << t << " ";
}
cout << endl << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,16 @@
/***Hanoi塔问题***/
#include"3.10.h"
int main() {
int n;
char a, b, c;
a = '1';
b = '2';
c = '3';
cout << "请输入初始第一个柱子上的圆盘个数:" << endl;
cin >> n;
cout << "将第一个柱子上的圆盘全部移动到第三个柱子上的过程为:" << endl;
Hanoi(n, a, b, c);
return 0;
}

View File

@@ -0,0 +1,20 @@
#include<iostream>
using namespace std;
int m = 0;//(m是初值为0的全局变量,对搬动计数)
void move(char A, int n, char C) // 搬动操作
{
cout << "第" << ++m << "步," << "将编号为" << n << "的圆盘从第" << A << "个柱子上移到第" << C
<< "个柱子上" << endl;
}
//算法3.10 Hanoi塔问题的递归算法
void Hanoi(int n, char A, char B, char C) {//将塔座A上的n个圆盘按规则搬到C上,B做辅助塔
if (n == 1)
move(A, 1, C); //将编号为1的圆盘从A移到C
else {
Hanoi(n - 1, A, C, B); //将A上编号为1至n-1的圆盘移到B,C做辅助塔
move(A, n, C);//将编号为n的圆盘从A移到C
Hanoi(n - 1, B, A, C); //将B上编号为1至n-1的圆盘移到C,A做辅助塔
}
}

View File

@@ -0,0 +1,123 @@
/***循环队列基本操作***/
#include<iostream>
#include<fstream>
using namespace std;
#define MAXQSIZE 100
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char QElemType;
typedef char SElemType;
typedef int Status;
typedef struct {
QElemType *base;//初始化时动态分配存储空间
int front;//头指针
int rear;//尾指针
} SqQueue;
//算法3.11 循环队列的初始化
Status InitQueue(SqQueue &Q) {//构造一个空队列Q
Q.base = new QElemType[MAXQSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
if (!Q.base)
exit(OVERFLOW); //存储分配失败
Q.front = Q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
//算法3.12 求循环队列的长度
int QueueLength(SqQueue Q) {//返回Q的元素个数,即队列的长度
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
//算法3.13 循环队列的入队
Status EnQueue(SqQueue &Q, QElemType e) {//插入元素e为Q的新的队尾元素
if ((Q.rear + 1) % MAXQSIZE == Q.front) //尾指针在循环意义上加1后等于头指针,表明队满
return ERROR;
Q.base[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MAXQSIZE; //队尾指针加1
return OK;
}
//算法3.14 循环队列的出队
Status DeQueue(SqQueue &Q, QElemType &e) {//删除Q的队头元素,用e返回其值
if (Q.front == Q.rear)
return ERROR; //队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front + 1) % MAXQSIZE; //队头指针加1
return OK;
}
//算法3.15 取循环队列的队头元素
SElemType GetHead(SqQueue Q) {//返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
int main() {
int choose, flag = 0;
SqQueue Q;
QElemType e, j;
cout << "1.初始化\n";
cout << "2.入队\n";
cout << "3.读队头元素\n";
cout << "4.出队\n";
cout << "0.退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1://算法3.16 链队的初始化
if (InitQueue(Q)) {
flag = 1;
cout << "成功对队列进行初始化\n\n";
} else
cout << "初始化队列失败\n\n";
break;
case 2: {//算法3.17 链队的入队
fstream file;
file.open("QNode.txt");
if (!file) {
cout << "错误!未找到文件!\n\n" << endl;
exit(ERROR);
}
if (flag) {
flag = 1;
cout << "入队的元素依次为:\n";
while (!file.eof()) {
file >> j;
if (file.fail())
break;
else {
EnQueue(Q, j);
cout << j << " ";
}
}
cout << endl << endl;
} else
cout << "队列未建立,请重新选择\n\n";
file.close();
}
break;
case 3://算法3.19 取链队的队头元素
if (flag != -1 && flag != 0)
cout << "队头元素为:\n" << GetHead(Q) << endl << endl;
else
cout << "队列中无元素,请重新选择\n" << endl;
break;
case 4://算法3.18 链队的出队
cout << "依次弹出的队头元素为:\n";
while (DeQueue(Q, e)) {
flag = -1;
cout << e << " ";
}
cout << endl << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,126 @@
/***链队的基本操作***/
#include<iostream>
#include<fstream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char QElemType;
typedef int Status;
typedef char SElemType;
//- - - - - 队列的链式存储结构- - - - -
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
} LinkQueue;
//算法3.16 链队的初始化
Status InitQueue(LinkQueue &Q) {//构造一个空队列Q
Q.front = Q.rear = new QNode; //生成新结点作为头结点,队头和队尾指针指向此结点
Q.front->next = NULL; //头结点的指针域置空
return OK;
}
//算法3.17 链队的入队
Status EnQueue(LinkQueue &Q, QElemType e) {//插入元素e为Q的新的队尾元素
QueuePtr p;
p = new QNode; //为入队元素分配结点空间,用指针p指向
p->data = e; //将新结点数据域置为e
p->next = NULL;
Q.rear->next = p; //将新结点插入到队尾
Q.rear = p; //修改队尾指针
return OK;
}
//算法3.18 链队的出队
Status DeQueue(LinkQueue &Q, QElemType &e) {//删除Q的队头元素,用e返回其值
QueuePtr p;
if (Q.front == Q.rear)
return ERROR; //若队列空,则返回ERROR
p = Q.front->next; //p指向队头元素
e = p->data; //e保存队头元素的值
Q.front->next = p->next; //修改头指针
if (Q.rear == p)
Q.rear = Q.front; //最后一个元素被删,队尾指针指向头结点
delete p; //释放原队头元素的空间
return OK;
}
//算法3.19 取链队的队头元素
SElemType GetHead(LinkQueue Q) {//返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.front->next->data; //返回队头元素的值,队头指针不变
}
int main() {
int choose, flag = 0;
LinkQueue Q;
QElemType e, j;
cout << "1.初始化\n";
cout << "2.入队\n";
cout << "3.读队头元素\n";
cout << "4.出队\n";
cout << "0.退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1://算法3.16 链队的初始化
if (InitQueue(Q)) {
flag = 1;
cout << "成功对队列进行初始化\n\n";
} else
cout << "初始化队列失败\n\n";
break;
case 2: {//算法3.17 链队的入队
fstream file;
file.open("QNode.txt");
if (!file) {
cout << "错误!未找到文件!\n\n" << endl;
exit(ERROR);
}
if (flag) {
flag = 1;
cout << "入队的元素依次为:\n";
while (!file.eof()) {
file >> j;
if (file.fail())
break;
else {
EnQueue(Q, j);
cout << j << " ";
}
}
cout << endl << endl;
} else
cout << "队列未建立,请重新选择\n\n";
file.close();
}
break;
case 3://算法3.19 取链队的队头元素
if (flag != -1 && flag != 0)
cout << "队头元素为:\n" << GetHead(Q) << endl << endl;
else
cout << "队列中无元素,请重新选择\n" << endl;
break;
case 4://算法3.18 链队的出队
cout << "依次弹出的队头元素为:\n";
while (DeQueue(Q, e)) {
flag = -1;
cout << e << " ";
}
cout << endl << endl;
break;
}
}
return 0;
}

View File

@@ -0,0 +1,69 @@
/***链栈实现数制的转换***/
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef struct SNode {
int data;
struct SNode *next;
} SNode, *LinkStack;
Status InitStack(LinkStack &S) {
S = NULL;
return OK;
}
bool StackEmpty(LinkStack S) {
if (!S)
return true;
return false;
}
Status Push(LinkStack &S, int e) {
LinkStack p;
p = new SNode;
if (!p) {
return OVERFLOW;
}
p->data = e;
p->next = S;
S = p;
return OK;
}
Status Pop(LinkStack &S, int &e) {
LinkStack p;
if (!S)
return ERROR;
e = S->data;
p = S;
S = S->next;
delete p;
return OK;
}
//算法3.20 数制的转换(链栈实现)
void conversion(int N) {//对于任意一个非负十进制数,打印输出与其等值的八进制数
int e;
LinkStack S;
InitStack(S); //初始化空栈S
while (N) //当N非零时,循环
{
Push(S, N % 8); //把N与8求余得到的八进制数压入栈S
N = N / 8; //N更新为N与8的商
}
while (!StackEmpty(S)) //当栈S非空时,循环
{
Pop(S, e); //弹出栈顶元素e
cout << e; //输出e
}
}
int main() {//对于输入的任意一个非负十进制数,打印输出与其等值的八进制数
int n, e;
cout << "输入一个非负十进制数:" << endl;
cin >> n;
conversion(n);
return 0;
}

View File

@@ -0,0 +1,96 @@
/***链栈实现括号匹配***/
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char SElemType;
typedef int Status;
typedef struct SNode {
int data;
struct SNode *next;
} SNode, *LinkStack;
Status InitStack(LinkStack &S) {
S = NULL;
return OK;
}
bool StackEmpty(LinkStack S) {
if (!S)
return true;
return false;
}
Status Push(LinkStack &S, SElemType e) {
SNode *p = new SNode;
if (!p) {
return OVERFLOW;
}
p->data = e;
p->next = S;
S = p;
return OK;
}
Status Pop(LinkStack &S, SElemType &e) {
SNode *p;
if (!S)
return ERROR;
e = S->data;
p = S;
S = S->next;
delete p;
return OK;
}
Status GetTop(LinkStack &S) {
if (!S)
return ERROR;
return S->data;
}
//算法3.21 括号的匹配
Status Matching() {//检验表达式中所含括号是否正确匹配,如果匹配,则返回true,否则返回false
//表达式以“#”结束
char ch;
SElemType x;
LinkStack S;
InitStack(S); //初始化空栈
int flag = 1; //标记匹配结果以控制循环及返回结果
cin >> ch; //读入第一个字符
while (ch != '#' && flag) //假设表达式以“#”结尾
{
switch (ch) {
case '[' :
case '(': //若是左括号,则将其压入栈
Push(S, ch);
break;
case ')': //若是“)”,则根据当前栈顶元素的值分情况考虑
if (!StackEmpty(S) && GetTop(S) == '(')
Pop(S, x); //若栈非空且栈顶元素是“(”,则正确匹配
else
flag = 0; //若栈空或栈顶元素不是“(”,则错误失败
break;
case ']': //若是“]”,则根据当前栈顶元素的值分情况考虑
if (!StackEmpty(S) && GetTop(S) == '[')
Pop(S, x); //若栈非空且栈顶元素是“[”,则正确匹配
else
flag = 0; //若栈空或栈顶元素不是“[”,则错误匹配
break;
} //switch
cin >> ch; //继续读入下一个字符
} //while
if (StackEmpty(S) && flag)
return true; //匹配成功
else
return false; //匹配失败
}
int main() {
LinkStack S;
cout << "请输入待匹配的表达式,以“#”结束:" << endl;
int flag = (int) Matching();
if (flag)
cout << "括号匹配成功!" << endl;
else
cout << "括号匹配失败!" << endl;
return 0;
}

View File

@@ -0,0 +1,29 @@
#include"3.22.h"
int menu() {
int c;
cout << "0-9以内的多项式计算" << endl;
cout << "1.计算" << endl;
cout << "0.退出\n" << endl;
cout << "选择:";
cin >> c;
return c;
}
void main() {
while (1) {
switch (menu()) {
case 1: {
cout << "请输入要计算的表达式(操作数和结果都在0-9的范围内,以#结束):" << endl;
char res = EvaluateExpression();//算法3.22 表达式求值
cout << "计算结果为" << res - 48 << endl << endl;
}
break;
case 0:
cout << "退出成功\n" << endl;
exit(0);
default:
break;
}
}
}

View File

@@ -0,0 +1,117 @@
/***链栈实现表达式求值***/
#include<iostream>
using namespace std;
const char oper[7] = { '+', '-', '*', '/', '(', ')', '#' };
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char SElemType;
typedef int Status;
typedef struct SNode {
int data;
struct SNode *next;
} SNode, *LinkStack;
Status InitStack(LinkStack &S) {
S = NULL;
return OK;
}
bool StackEmpty(LinkStack S) {
if (!S)
return true;
return false;
}
Status Push(LinkStack &S, SElemType e) {
SNode *p = new SNode;
if (!p) {
return OVERFLOW;
}
p->data = e;
p->next = S;
S = p;
return OK;
}
Status Pop(LinkStack &S, SElemType &e) {
SNode *p;
if (!S)
return ERROR;
e = S->data;
p = S;
S = S->next;
delete p;
return OK;
}
Status GetTop(LinkStack &S) {
if (!S)
return ERROR;
return S->data;
}
bool In(char ch) {//判断ch是否为运算符
for (int i = 0; i < 7; i++) {
if (ch == oper[i]) {
return true;
}
}
return false;
}
char Precede(char theta1, char theta2) {//判断运算符优先级
if ((theta1 == '(' && theta2 == ')') || (theta1 == '#' && theta2 == '#')) {
return '=';
} else if (theta1 == '(' || theta1 == '#' || theta2 == '(' || (theta1
== '+' || theta1 == '-') && (theta2 == '*' || theta2 == '/')) {
return '<';
} else
return '>';
}
char Operate(char first, char theta, char second) {//计算两数运算结果
switch (theta) {
case '+':
return (first - '0') + (second - '0') + 48;
case '-':
return (first - '0') - (second - '0') + 48;
case '*':
return (first - '0') * (second - '0') + 48;
case '/':
return (first - '0') / (second - '0') + 48;
}
return 0;
}
//算法3.22 表达式求值
char EvaluateExpression() {//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈
LinkStack OPTR, OPND;
char ch, theta, a, b, x, top;
InitStack(OPND); //初始化OPND栈
InitStack(OPTR); //初始化OPTR栈
Push(OPTR, '#'); //将表达式起始符“#”压入OPTR栈
cin >> ch;
while (ch != '#' || (GetTop(OPTR) != '#')) //表达式没有扫描完毕或OPTR的栈顶元素不为“#”
{
if (!In(ch)) {
Push(OPND, ch);
cin >> ch;
} //ch不是运算符则进OPND栈
else
switch (Precede(GetTop(OPTR), ch)) //比较OPTR的栈顶元素和ch的优先级
{
case '<':
Push(OPTR, ch);
cin >> ch; //当前字符ch压入OPTR栈,读入下一字符ch
break;
case '>':
Pop(OPTR, theta); //弹出OPTR栈顶的运算符
Pop(OPND, b);
Pop(OPND, a); //弹出OPND栈顶的两个运算数
Push(OPND, Operate(a, theta, b)); //将运算结果压入OPND栈
break;
case '=': //OPTR的栈顶元素是“(”且ch是“)”
Pop(OPTR, x);
cin >> ch; //弹出OPTR栈顶的“(”,读入下一字符ch
break;
} //switch
} //while
return GetTop(OPND); //OPND栈顶元素即为表达式求值结果
}

View File

@@ -0,0 +1,18 @@
#include"3.23.h"
Person dancer[MAXQSIZE];
int main() {
int i = 0;
fstream file;
file.open("DancePartner.txt");
if (!file) {
cout << "错误!未找到文件!\n\n" << endl;
exit( ERROR);
}
while (!file.eof()) {
file >> dancer[i].name >> dancer[i].sex;
i++;
}
DancePartner(dancer, i + 1);
return 0;
}

View File

@@ -0,0 +1,89 @@
#include<iostream>
#include<fstream>
#include<string>
#define MAXQSIZE 100//队列可能达到的最大长度
#define OK 1
#define ERROR 0
#define OVERFLOW -2
using namespace std;
typedef struct {
char name[20]; //姓名
char sex; //性别,'F'表示女性,'M'表示男性
} Person;
//- - - - - 队列的顺序存储结构- - - - -
typedef struct {
Person *base; //队列中数据元素类型为Person
int front; //头指针
int rear; //尾指针
} SqQueue;
SqQueue Mdancers, Fdancers; //分别存放男士和女士入队者队列
int InitQueue(SqQueue &Q) {//构造一个空队列Q
Q.base = new Person[MAXQSIZE]; //为队列分配一个最大容量为MAXSIZE的数组空间
if (!Q.base)
exit( OVERFLOW); //存储分配失败
Q.front = Q.rear = 0; //头指针和尾指针置为零,队列为空
return OK;
}
int EnQueue(SqQueue &Q, Person e) {//插入元素e为Q的新的队尾元素
if ((Q.rear + 1) % MAXQSIZE == Q.front) //尾指针在循环意义上加1后等于头指针,表明队满
return ERROR;
Q.base[Q.rear] = e; //新元素插入队尾
Q.rear = (Q.rear + 1) % MAXQSIZE; //队尾指针加1
return OK;
}
int QueueEmpty(SqQueue &Q) {
if (Q.front == Q.rear) //队空
return OK;
else
return ERROR;
}
int DeQueue(SqQueue &Q, Person &e)//删除Q的队头元素,用e返回其值
{
if (Q.front == Q.rear)
return ERROR; //队空
e = Q.base[Q.front]; //保存队头元素
Q.front = (Q.front + 1) % MAXQSIZE; //队头指针加1
return OK;
}
Person GetHead(SqQueue Q) {//返回Q的队头元素,不修改队头指针
if (Q.front != Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变
}
//算法3.23 舞伴问题
void DancePartner(Person dancer[], int num) {//结构数组dancer中存放跳舞的男女,num是跳舞的人数。
InitQueue(Mdancers); //男士队列初始化
InitQueue(Fdancers); //女士队列初始化
Person p;
for (int i = 0; i < num; i++) //依次将跳舞者根据其性别入队
{
p = dancer[i];
if (p.sex == 'F')
EnQueue(Fdancers, p); //插入女队
else
EnQueue(Mdancers, p); //插入男队
}
cout << "The dancing partners are:" << endl;
while (!QueueEmpty(Fdancers) && !QueueEmpty(Mdancers)) {//依次输出男女舞伴的姓名
DeQueue(Fdancers, p); //女士出队
cout << p.name << " "; //输出出队女士姓名
DeQueue(Mdancers, p); //男士出队
cout << p.name << endl; //输出出队男士姓名
}
if (!QueueEmpty(Fdancers)) { //女士队列非空,输出队头女士的姓名
p = GetHead(Fdancers); //取女士队头
cout << "The first man to get a partner is: " << endl;
cout << p.name << endl;
} else if (!QueueEmpty(Mdancers)) { //男士队列非空,输出队头男士的姓名
p = GetHead(Mdancers); //取男士队头
cout << "The first woman to get a partner is: " << p.name << endl;
}
}

View File

@@ -0,0 +1,18 @@
鄢雪棱 F
高欣雅 F
张甜源 F
许丹丹 F
冉小溪 F
周如意 F
胡思琪 F
蒋雅琪 F
金城武 M
吴彦祖 M
王思聪 M
古天乐 M
周杰伦 M
李敏浩 M
李钟硕 M
马小云 M
张智霖 M
王力宏 M

View File

@@ -0,0 +1,115 @@
/***链栈的实现***/
#include<iostream>
#include<fstream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef char SElemType;
typedef struct StackNode {
SElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
//算法3.5 链栈的初始化
Status InitStack(LinkStack &S) { // 构造一个空栈 S,栈顶指针置空
S = NULL;
return OK;
}
//算法3.6 链栈的入栈
Status Push(LinkStack &S, SElemType e) {//在栈顶插入元素e
LinkStack p;
p = new StackNode; //生成新结点
p->data = e; //将新结点数据域置为e
p->next = S; //将新结点插入栈顶
S = p; //修改栈顶指针为p
return OK;
}
//算法3.7 链栈的出栈
Status Pop(LinkStack &S, SElemType &e) {//删除S的栈顶元素,用e返回其值
LinkStack p;
if (S == NULL)
return ERROR; //栈空
e = S->data; //将栈顶元素赋给e
p = S; //用p临时保存栈顶元素空间,以备释放
S = S->next; //修改栈顶指针
delete p; //释放原栈顶元素的空间
return OK;
}
//算法3.8 取链栈的栈顶元素
SElemType GetTop(LinkStack S) {//返回S的栈顶元素,不修改栈顶指针
if (S != NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
}
int main() {
LinkStack s;
int choose, flag = 0;
SElemType j, t;
cout << "1.初始化\n";
cout << "2.入栈\n";
cout << "3.读栈顶元素\n";
cout << "4.出栈\n";
cout << "0.退出\n\n";
choose = -1;
while (choose != 0) {
cout << "请选择:";
cin >> choose;
switch (choose) {
case 1://算法3.5 链栈的初始化
if (InitStack(s)) {
flag = 1;
cout << "成功对栈进行初始化\n\n";
} else
cout << "初始化栈失败\n\n";
break;
case 2: {//算法3.6 链栈的入栈
fstream file;
file.open("SqStack.txt");
if (!file) {
cout << "错误!未找到文件!\n\n" << endl;
exit(ERROR);
}
if (flag) {
flag = 1;
cout << "进栈元素依次为:\n";
while (!file.eof()) {
file >> j;
if (file.fail())
break;
else {
Push(s, j);
cout << j << " ";
}
}
cout << endl << endl;
} else
cout << "栈未建立,请重新选择\n\n";
file.close();
}
break;
case 3://算法3.8 取链栈的栈顶元素
if (flag != -1 && flag != 0)
cout << "栈顶元素为:\n" << GetTop(s) << endl << endl;
else
cout << "栈中无元素,请重新选择\n" << endl;
break;
case 4://算法3.7 链栈的出栈
if (flag) {
cout << "依次弹出的栈顶元素为:\n";
while (Pop(s, t))
cout << t << " ";
cout << endl << endl;
} else
cout << "栈未建立,请重新选择\n\n";
break;
}
}
return 0;
}

View File

@@ -0,0 +1,53 @@
/***依次输出链表中的各个结点***/
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef char ElemType;
typedef struct LNode {
ElemType data; //结点的数据域
LNode *next; //结点的指针域
} LNode, *LinkList;//头指针
//后插法创建链表算法
void CreateList_L(LinkList &L, int n) {
L = new LNode;
L->next = NULL;
LNode *p, *r;
r = L;
for (int i = 0; i < n; i++) {
p = new LNode;
cin >> p->data;
p->next = NULL;
r->next = p;
r = p;
}
}
//算法3.9 遍历输出链表中各个结点的递归算法
void TraverseList(LinkList p) {
if (p == NULL)
return; //递归终止
else {
cout << p->data << endl; //输出当前结点的数据域
TraverseList(p->next); //p指向后继指点继续递归
}
}
int main() {
int n;
LinkList L;
//InitList(L);
cout << "请输入元素个数:" << endl;
cin >> n;
cout << "请输入链表元素(以空格隔开,按回车结束):" << endl;
CreateList_L(L, n); //后插法创建链表算法
cout << "链表中的元素依次为:" << endl;
TraverseList(L->next);
cout << endl;
return 0;
}

View File

@@ -0,0 +1,60 @@
/***字符串匹配算法***/
#include<cstring>
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
int i;
if (strlen(chars) > MAXSTRLEN)
return ERROR;
else {
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
T[i] = *(chars + i - 1);
return OK;
}
}
//算法4.1 BF算法
int Index(SString S, SString T, int pos)
{
//返回模式T在主串S中第pos个字符之后第s一次出现的位置。若不存在,则返回值为0
//其中,T非空,1≤pos≤StrLength(S)
int i = pos;
int j = 1;
while(i <= S[0]&&j <= T[0])
{
if(S[i]==T[j])
{
++i;
++j;
} //继续比较后继字符
else
{
i=i-j+2;
j=1;
} //指针后退重新开始匹配
}
if (j > T[0])
return i - T[0];
else
return 0;
return 0;
}//Index
int main()
{
SString S;
StrAssign(S,"bbaaabbaba") ;
SString T;
StrAssign(T,"abb") ;
cout<<"主串和子串在第"<<Index(S,T,1)<<"个字符处首次匹配\n";
return 0;
}

View File

@@ -0,0 +1,69 @@
/***字符串匹配算法***/
#include<cstring>
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
int i;
if (strlen(chars) > MAXSTRLEN)
return ERROR;
else {
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
T[i] = *(chars + i - 1);
return OK;
}
}
//算法4.3 计算next函数值
void get_next(SString T, int next[])
{ //求模式串T的next函数值并存入数组next
int i = 1, j = 0;
next[1] = 0;
while (i < T[0])
if (j == 0 || T[i] == T[j])
{
++i;
++j;
next[i] = j;
}
else
j = next[j];
}//get_next
//算法4.2 KMP算法
int Index_KMP(SString S, SString T, int pos, int next[])
{ // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1≤pos≤StrLength(S)
int i = pos, j = 1;
while (i <= S[0] && j <= T[0])
if (j == 0 || S[i] == T[j]) // 继续比较后继字
{
++i;
++j;
}
else
j = next[j]; // 模式串向右移动
if (j > T[0]) // 匹配成功
return i - T[0];
else
return 0;
}//Index_KMP
int main()
{
SString S;
StrAssign(S,"aaabbaba") ;
SString T;
StrAssign(T,"abb") ;
int *p = new int[T[0]+1]; // 生成T的next数组
get_next(T,p);
cout<<"主串和子串在第"<<Index_KMP(S,T,1,p)<<"个字符处首次匹配\n";
return 0;
}

View File

@@ -0,0 +1,72 @@
/***字符串匹配算法***/
#include<cstring>
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
#define MAXSTRLEN 255 //用户可在255以内定义最长串长
typedef char SString[MAXSTRLEN+1]; //0号单元存放串的长度
Status StrAssign(SString T, char *chars) { //生成一个其值等于chars的串T
int i;
if (strlen(chars) > MAXSTRLEN)
return ERROR;
else {
T[0] = strlen(chars);
for (i = 1; i <= T[0]; i++)
T[i] = *(chars + i - 1);
return OK;
}
}
//算法4.4 计算next函数修正值
void get_nextval(SString T, int nextval[])
{ // 求模式串T的next函数修正值并存入数组nextval
int i = 1, j = 0;
nextval[1] = 0;
while (i < T[0])
if (j == 0 || T[i] == T[j])
{
++i;
++j;
if (T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
} else
j = nextval[j];
}//get_nextval
//算法4.2 KMP算法
int Index_KMP(SString S, SString T, int pos, int next[])
{ // 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1≤pos≤StrLength(S)
int i = pos, j = 1;
while (i <= S[0] && j <= T[0])
if (j == 0 || S[i] == T[j]) // 继续比较后继字
{
++i;
++j;
}
else
j = next[j]; // 模式串向右移动
if (j > T[0]) // 匹配成功
return i - T[0];
else
return 0;
}//Index_KMP
int main()
{
SString S;
StrAssign(S,"babaaaabbaba") ;
SString T;
StrAssign(T,"abb") ;
int *p = new int[T[0]+1]; // 生成T的next数组
get_nextval(T,p);
cout<<"主串和子串在第"<<Index_KMP(S,T,1,p)<<"个字符处首次匹配\n";
return 0;
}

View File

@@ -0,0 +1,69 @@
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
typedef struct{
char ch[600]; //若是非空串,则按串长分配存储区,否则ch为NULL
int len; //串长度
}HString;
int Index_BF(HString S,HString T,int pos)
{//返回模式T在主串S中第pos个字符开始第一次出现的位置。若不存在,则返回值为0
//其中,T非空,1≤pos≤StrLength(S)
int i,j;
i=pos; j=1;
while(i<=S.len&&j<=T.len)
{
if(S.ch[i]==T.ch[j]){++i;++j;} //继续比较后继字符
else{i=i-j+2;j=1;} //指针后退重新开始匹配
}
if(j>T.len) return i-T.len;
else return 0;
}
void Virus_detection()
{
int num,m,flag,i,j; char Vir[600];
HString Virus,Person,temp;
ifstream inFile("病毒感染检测输入数据.txt");
ofstream outFile("病毒感染检测输出结果.txt");
inFile>>num;//读取待检测的任务数
while(num--) //依次检测每对病毒DNA和人的DNA是否匹配
{
inFile>>Virus.ch+1;//读取病毒DNA序列
inFile>>Person.ch+1;//读取人的DNA序列
strcpy(Vir,Virus.ch);
Virus.len=strlen(Virus.ch)-1;
Person.len=strlen(Person.ch)-1;
flag=0;//用来标识是否匹配,初始为0,匹配后为非0
m=Virus.len;
for(i=m+1,j=1;j<=m;j++) Virus.ch[i++]=Virus.ch[j];
//因病毒为环状,故将病毒的长度扩大2倍
//即可线性取到所有长度为Virus.len的字符串
Virus.ch[2*m+1]='\0'; //添加结束符号
for(i=0;i<m;i++)
{
for(j=1;j<=m;j++) temp.ch[j]=Virus.ch[i+j];
//取长为Virus.len的环形字符串
//即Virus.ch[0]-- Virus.ch[Virus.len-1],
//Virus.ch[1]-- Virus.ch[0], Virus.ch[2]-- Virus.ch[1]...
temp.ch[m+1]='\0'; //添加结束符号
temp.len=strlen(temp.ch)-1;
flag=Index_BF(Person,temp,1); //模式匹配
if(flag) break; //匹配即可退出循环
}//for
if(flag)
outFile<<Vir+1<<" "<<Person.ch+1<<" "<<"YES"<<endl;
else
outFile<<Vir+1<<" "<<Person.ch+1<<" "<<"NO"<<endl;
}//while
}
int main()
{
Virus_detection();
return 0;
}

View File

@@ -0,0 +1,12 @@
11
baa bbaabbba
baa aaabbbba
aabb abceaabb
aabb abaabcea
abcd cdabbbab
abcd cabbbbab
abcde bcdedbda
acc bdedbcda
cde cdcdcdec
cced cdccdcce
bcd aabccdxdxbxa

View File

@@ -0,0 +1,39 @@
//算法5.1 中序遍历的递归算法
#include<iostream>
using namespace std;
typedef struct BiNode{ //二叉链表定义
char data;
struct BiNode *lchild,*rchild;
}BiTNode,*BiTree;
//用算法5.3 先序遍历的顺序建立二叉链表
void CreateBiTree(BiTree &T){
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void InOrderTraverse(BiTree T){
//中序遍历二叉树T的递归算法
if(T){
InOrderTraverse(T->lchild);
cout << T->data;
InOrderTraverse(T->rchild);
}
}
void main(){
BiTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
cout<<"中序遍历的结果为:\n";
InOrderTraverse(tree);
cout<<endl;
}

View File

@@ -0,0 +1,69 @@
//算法5.10 构造赫夫曼树
#include<iostream>
using namespace std;
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
int i,min1=0x3f3f3f3f,min2=0x3f3f3f3f;//先赋予最大值
for(i=1;i<=len;i++)
{
if(HT[i].weight<min1&&HT[i].parent==0)
{
min1=HT[i].weight;
s1=i;
}
}
int temp=HT[s1].weight;//将原值存放起来,然后先赋予最大值,防止s1被重复选择
HT[s1].weight=0x3f3f3f3f;
for(i=1;i<=len;i++)
{
if(HT[i].weight<min2&&HT[i].parent==0)
{
min2=HT[i].weight;
s2=i;
}
}
HT[s1].weight=temp;//恢复原来的值
}
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
//构造赫夫曼树HT
int m,s1,s2,i;
if(n<=1) return;
m=2*n-1;
HT=new HTNode[m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点
for(i=1;i<=m;++i) //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0
{ HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; }
cout<<"请输入叶子结点的权值:\n";
for(i=1;i<=n;++i) //输入前n个单元中叶子结点的权值
cin>>HT[i].weight;
/*――――――――――初始化工作结束,下面开始创建赫夫曼树――――――――――*/
for(i=n+1;i<=m;++i)
{ //通过n-1次的选择、删除、合并来创建赫夫曼树
Select(HT,i-1,s1,s2);
//在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点,
// 并返回它们在HT中的序号s1和s2
HT[s1].parent=i;
HT[s2].parent=i;
//得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i
HT[i].lchild=s1;
HT[i].rchild=s2 ; //s1,s2分别作为i的左右孩子
HT[i].weight=HT[s1].weight+HT[s2].weight; //i 的权值为左右孩子权值之和
} //for
} // CreatHuffmanTree
void main()
{
HuffmanTree HT;
int n;
cout<<"请输入叶子结点的个数:\n";
cin>>n;
CreatHuffmanTree(HT,n);
cout<<"哈夫曼树建立完毕!\n";
}

View File

@@ -0,0 +1,105 @@
//算法5.11 根据赫夫曼树求赫夫曼编码
#include<iostream>
using namespace std;
typedef struct
{
int weight;
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
int i,min1=0x3f3f3f3f,min2=0x3f3f3f3f;//先赋予最大值
for(i=1;i<=len;i++)
{
if(HT[i].weight<min1&&HT[i].parent==0)
{
min1=HT[i].weight;
s1=i;
}
}
int temp=HT[s1].weight;//将原值存放起来,然后先赋予最大值,防止s1被重复选择
HT[s1].weight=0x3f3f3f3f;
for(i=1;i<=len;i++)
{
if(HT[i].weight<min2&&HT[i].parent==0)
{
min2=HT[i].weight;
s2=i;
}
}
HT[s1].weight=temp;//恢复原来的值
}
//用算法5.10构造赫夫曼树
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
//构造赫夫曼树HT
int m,s1,s2,i;
if(n<=1) return;
m=2*n-1;
HT=new HTNode[m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点
for(i=1;i<=m;++i) //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0
{ HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; }
cout<<"请输入叶子结点的权值:\n";
for(i=1;i<=n;++i) //输入前n个单元中叶子结点的权值
cin>>HT[i].weight;
/*――――――――――初始化工作结束,下面开始创建赫夫曼树――――――――――*/
for(i=n+1;i<=m;++i)
{ //通过n-1次的选择、删除、合并来创建赫夫曼树
Select(HT,i-1,s1,s2);
//在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点,
// 并返回它们在HT中的序号s1和s2
HT[s1].parent=i;
HT[s2].parent=i;
//得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i
HT[i].lchild=s1;
HT[i].rchild=s2 ; //s1,s2分别作为i的左右孩子
HT[i].weight=HT[s1].weight+HT[s2].weight; //i 的权值为左右孩子权值之和
} //for
}
// CreatHuffmanTree
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
//从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中
int i,start,c,f;
HC=new char*[n+1]; //分配n个字符编码的头指针矢量
char *cd=new char[n]; //分配临时存放编码的动态数组空间
cd[n-1]='\0'; //编码结束符
for(i=1;i<=n;++i)
{ //逐个字符求赫夫曼编码
start=n-1; //start开始时指向最后,即编码结束符位置
c=i;
f=HT[i].parent; //f指向结点c的双亲结点
while(f!=0)
{ //从叶子结点开始向上回溯,直到根结点
--start; //回溯一次start向前指一个位置
if(HT[f].lchild==c)
cd[start]='0'; //结点c是f的左孩子,则生成代码0
else
cd[start]='1'; //结点c是f的右孩子,则生成代码1
c=f;
f=HT[f].parent; //继续向上回溯
} //求出第i个字符的编码
HC[i]=new char[n-start]; // 为第i 个字符编码分配空间
strcpy(HC[i], &cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中
}
delete cd; //释放临时空间
} // CreatHuffanCode
void show(HuffmanTree HT,HuffmanCode HC)
{
for(int i=1;i<=sizeof(HC)+1;i++)
cout<<HT[i].weight<<"编码为"<<HC[i]<<endl;
}
void main()
{
HuffmanTree HT;
HuffmanCode HC;
int n;
cout<<"请输入叶子结点的个数:\n";
cin>>n; //输入赫夫曼树的叶子结点个数
CreatHuffmanTree(HT,n);
CreatHuffmanCode(HT,HC,n);
show(HT,HC);
}

View File

@@ -0,0 +1,201 @@
#include<iostream>
#include<string>
#define ERROR -1
#define MAXSIZE 100
using namespace std;
typedef struct BiTNode{ //二叉树的二叉链表存储表示
char data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef struct{ // 字符栈定义
char *base;
char *top;
int stacksize;
}SqStack;
typedef struct{ //树栈定义
BiTree *base;
BiTree *top;
int stacksize;
}BiTreeStack;
void InitStack(SqStack &S){ //字符栈初始化
S.base=new char[MAXSIZE];
if(!S.base) exit(-1);
S.top=S.base;
S.stacksize=MAXSIZE;
}
void InitBiTreeStack(BiTreeStack &S){ //树栈初始化
S.base=new BiTree[MAXSIZE];
if(!S.base) exit(-1);
S.top=S.base;
S.stacksize=MAXSIZE;
}
void Push(SqStack &S,char e) //字符栈入栈
{
if(S.top-S.base==S.stacksize) return ;
*S.top=e;
S.top++;
}
void PushBiTree(BiTreeStack &S,BiTree e) //树栈入栈
{
if(S.top-S.base==S.stacksize) return ;
*S.top=e;
S.top++;
}
void Pop(SqStack &S,char &e) //字符栈出栈
{
if(S.top==S.base) return;
e=*--S.top;
}
void PopBiTree(BiTreeStack &S,BiTree &e) //树栈出栈
{
if(S.top==S.base) return;
e=*--S.top;
}
char GetTop(SqStack &S) //字符栈得到栈顶函数
{
if(S.top==S.base) exit(1);
return *(S.top-1);
}
char Precede(char t1,char t2)
{ /* 根据教科书表3.1,判断两符号的优先关系 */
char f;
switch(t2)
{
case '+':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
case '-':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
case '*':if(t1=='*'||t1=='/'||t1==')')
f='>';
else
f='<';
break;
case '/':if(t1=='*'||t1=='/'||t1==')')
f='>';
else
f='<';
break;
case '(':if(t1!=')')
f='<';
break;
case')':if(t1=='(')
f='=';
else
f='>';
break;
case'#':if(t1=='#')
f='=';
else
f='>';
}
return f;
}
int In(char c)
{ /* 判断c是否为运算符 */
switch(c)
{
case '+':
case'-':
case'*':
case '/':
case'#':
case '(':
case')':return 1;break;
default:return 0;
}
}
int GetValue(char theta,int a,int b) //进行运算的函数
{
int c;
switch(theta)
{
case '+':c=a+b;break;
case'-':c=a-b;break;
case'*':c=a*b;break;
case'/':c=a/b;break;
default:
break;
}
return c;
}
void CreateExpTree(BiTree &T,BiTree a,BiTree b,char ch){ //简单二叉树的创建
T=new BiTNode;
T->data=ch;
T->lchild=a;
T->rchild=b;
}
void InitExpTree(BiTree &T) //算法5.12 表达式树的创建
{
SqStack OPTR;
BiTreeStack EXPT;
char ch,theta,x;
BiTree a,b;
InitStack(OPTR);Push(OPTR,'#');
InitBiTreeStack(EXPT);cin>>ch;
while(ch!='#'||GetTop(OPTR)!='#'){
if(!In(ch)){CreateExpTree(T,NULL,NULL,ch);PushBiTree(EXPT,T);cin>>ch;}//*q
else
switch(Precede(GetTop(OPTR),ch)){
case'<':
Push(OPTR,ch);cin>>ch;
break;
case'>':
Pop(OPTR,theta);
PopBiTree(EXPT,b);PopBiTree(EXPT,a);
CreateExpTree(T,a,b,theta); //*
PushBiTree(EXPT,T);
break;
case'=':
Pop(OPTR,x);cin>>ch;
break;
}
}
}
int EvaluateExTree(BiTree T){ //算法5.13 表达式树的求值
int lvalue,rvalue;
lvalue=rvalue=0;
if(T->lchild==NULL&&T->rchild==NULL)
return T->data-'0';
else{
lvalue=EvaluateExTree(T->lchild);
rvalue=EvaluateExTree(T->rchild);
return GetValue(T->data,lvalue,rvalue); //运算函数
}
}
void main()
{
cout<<"请输入算术表达式,并以#结束,中间计算过程要是个位数."<<endl;
BiTree T;
InitExpTree(T); //创建表达式树
cout<<EvaluateExTree(T)<<endl; //输出值
}

View File

@@ -0,0 +1,97 @@
//算法5.2 中序遍历的非递归算法
#include<iostream>
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//链栈的定义
typedef struct StackNode
{
BiTNode data;
struct StackNode *next;
}StackNode,*LinkStack;
//用算法5.3 先序遍历的顺序建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void InitStack(LinkStack &S)
{
//构造一个空栈S,栈顶指针置空
S=NULL;
}
bool StackEmpty(LinkStack S)
{
if(!S)
return true;
return false;
}
void Push(LinkStack &S,BiTree e)
{
//在栈顶插入元素*e
StackNode *p=new StackNode;
p->data=*e;
p->next=S;
S=p;
}
void Pop(LinkStack &S,BiTree e)
{
if(S!=NULL)//原书上写的是if(S==NULL)return ERROR;
{
*e=S->data;
StackNode *p=S;
S=S->next;
delete p;
}
}
void InOrderTraverse1(BiTree T)
{
// 中序遍历二叉树T的非递归算法
LinkStack S; BiTree p;
BiTree q=new BiTNode;
InitStack(S); p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p); //p非空根指针进栈,遍历左子树
p=p->lchild;
}
else
{
Pop(S,q); //p为空根指针退栈,访问根结点,遍历右子树
cout<<q->data;
p=q->rchild;
}
} // while
} // InOrderTraverse
void main()
{
BiTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
cout<<"中序遍历的结果为:\n";
InOrderTraverse1(tree);
cout<<endl;
}

View File

@@ -0,0 +1,44 @@
//算法5.3 先序遍历的的顺序建立二叉链表
#include<iostream>
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
//用算法5.1 中序遍历的递归算法
void InOrderTraverse(BiTree T)
{
//中序遍历二叉树T的递归算法
if(T){
InOrderTraverse(T->lchild);
cout << T->data;
InOrderTraverse(T->rchild);
}
}
void main()
{
BiTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
cout<<"所建立的二叉链表中序序列:\n";
InOrderTraverse(tree);
cout<<endl;
}

View File

@@ -0,0 +1,62 @@
//算法5.4 复制二叉树
#include<iostream>
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void Copy(BiTree T, BiTree &NewT)
{
if(T==NULL )
{ //如果是空树,递归结束
NewT=NULL;
return;
}
else
{
NewT=new BiTNode;
NewT->data= T->data; //复制根结点
Copy(T->lchild, NewT->lchild); //递归复制左子树
Copy(T->rchild, NewT->rchild); //递归复制右子树
} //else
} //CopyBiTree
//用算法5.1 中序遍历的递归算法
void InOrderTraverse(BiTree T)
{
//中序遍历二叉树T的递归算法
if(T){
InOrderTraverse(T->lchild);
cout << T->data;
InOrderTraverse(T->rchild);
}
}
void main()
{
BiTree tree,new_tree;
cout<<"请输入建立二叉树的序列:\n";
CreateBiTree(tree);
Copy(tree,new_tree);
cout<<"复制得到的新树的中序序列:\n";
InOrderTraverse(new_tree);
cout<<endl;
}

View File

@@ -0,0 +1,47 @@
//算法5.5 计算二叉树的深度
#include<iostream>
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
int Depth(BiTree T)
{
int m,n;
if(T == NULL ) return 0; //如果是空树,深度为0,递归结束
else
{
m=Depth(T->lchild); //递归计算左子树的深度记为m
n=Depth(T->rchild); //递归计算右子树的深度记为n
if(m>n) return(m+1); //二叉树的深度为m 与n的较大者加1
else return (n+1);
}
}
void main()
{
BiTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
cout<<"数的深度为:"<<Depth(tree)<<endl;
}

View File

@@ -0,0 +1,41 @@
//算法5.6 统计二叉树中结点的个数
#include<iostream>
using namespace std;
//二叉树的二叉链表存储表示
typedef struct BiNode
{
char data; //结点数据域
struct BiNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
//用算法5.3建立二叉链表
void CreateBiTree(BiTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else{
T=new BiTNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
int NodeCount(BiTree T)
{
if(T==NULL) return 0; // 如果是空树,则结点个数为0,递归结束
else return NodeCount(T->lchild)+ NodeCount(T->rchild) +1;
//否则结点个数为左子树的结点个数+右子树的结点个数+1
}
void main()
{
BiTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
cout<<"结点个数为:"<<NodeCount(tree)<<endl;
}

View File

@@ -0,0 +1,66 @@
//算法5.7 以结点P为根的子树中序线索化
#include<iostream>
using namespace std;
//二叉树的二叉线索类型存储表示
typedef struct BiThrNode
{
char data; //结点数据域
struct BiThrNode *lchild,*rchild; //左右孩子指针
int LTag,RTag;
}BiThrNode,*BiThrTree;
//全局变量pre
BiThrNode *pre=new BiThrNode;
//用算法5.3建立二叉链表
void CreateBiTree(BiThrTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BiThrNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
void InThreading(BiThrTree p)
{
//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
if(p)
{
InThreading(p->lchild); //左子树递归线索化
if(!p->lchild)
{ //p的左孩子为空
p->LTag=1; //给p加上左线索
p->lchild=pre; //p的左孩子指针指向pre(前驱)
}
else
p->LTag=0;
if(!pre->rchild)
{ //pre的右孩子为空
pre->RTag=1; //给pre加上右线索
pre->rchild=p; //pre的右孩子指针指向p(后继)
}
else
pre->RTag=0;
pre=p; //保持pre指向p的前驱
InThreading(p->rchild); //右子树递归线索化
}
}//InThreading
void main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
InThreading(tree);
cout<<"线索化完毕!\n";
}

View File

@@ -0,0 +1,85 @@
//算法5.8 带头结点的中序线索化
#include<iostream>
using namespace std;
//二叉树的二叉线索类型存储表示
typedef struct BiThrNode
{
char data; //结点数据域
struct BiThrNode *lchild,*rchild; //左右孩子指针
int LTag,RTag;
}BiThrNode,*BiThrTree;
//全局变量pre
BiThrNode *pre=new BiThrNode;
//用算法5.3建立二叉链表
void CreateBiTree(BiThrTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BiThrNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
//用算法5.7 以结点P为根的子树中序线索化
void InThreading(BiThrTree p)
{
//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
if(p)
{
InThreading(p->lchild); //左子树递归线索化
if(!p->lchild)
{ //p的左孩子为空
p->LTag=1; //给p加上左线索
p->lchild=pre; //p的左孩子指针指向pre(前驱)
}
else
p->LTag=0;
if(!pre->rchild)
{ //pre的右孩子为空
pre->RTag=1; //给pre加上右线索
pre->rchild=p; //pre的右孩子指针指向p(后继)
}
else
pre->RTag=0;
pre=p; //保持pre指向p的前驱
InThreading(p->rchild); //右子树递归线索化
}
}//InThreading
void InOrderThreading (BiThrTree &Thrt,BiThrTree T)
{
//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
Thrt=new BiThrNode; //建头结点
Thrt->LTag=0; //头结点有左孩子,若树非空,则其左孩子为树根
Thrt->RTag=1; //头结点的右孩子指针为右线索
Thrt->rchild=Thrt; //初始化时右指针指向自己
if(!T) Thrt->lchild=Thrt; //若树为空,则左指针也指向自己
else
{
Thrt->lchild=T; pre=Thrt; //头结点的左孩子指向根,pre初值指向头结点
InThreading(T); //调用算法5.7,对以T为根的二叉树进行中序线索化
pre->rchild=Thrt; //算法5.7结束后,pre为最右结点,pre的右线索指向头结点
pre->RTag=1;
Thrt->rchild=pre; //头结点的右线索指向pre
}
} //InOrderThreading
void main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree,Thrt;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
InOrderThreading(Thrt,tree);
cout<<"线索化完毕!\n";
}

View File

@@ -0,0 +1,108 @@
//算法5.9 遍历中序线索二叉树
#include<iostream>
using namespace std;
//二叉树的二叉线索类型存储表示
typedef struct BiThrNode
{
char data; //结点数据域
struct BiThrNode *lchild,*rchild; //左右孩子指针
int LTag,RTag;
}BiThrNode,*BiThrTree;
//全局变量pre
BiThrNode *pre=new BiThrNode;
//用算法5.3建立二叉链表
void CreateBiTree(BiThrTree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin >> ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BiThrNode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
} //else
} //CreateBiTree
//用算法5.7以结点P为根的子树中序线索化
void InThreading(BiThrTree p)
{
//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
if(p)
{
InThreading(p->lchild); //左子树递归线索化
if(!p->lchild)
{ //p的左孩子为空
p->LTag=1; //给p加上左线索
p->lchild=pre; //p的左孩子指针指向pre(前驱)
}
else
p->LTag=0;
if(!pre->rchild)
{ //pre的右孩子为空
pre->RTag=1; //给pre加上右线索
pre->rchild=p; //pre的右孩子指针指向p(后继)
}
else
pre->RTag=0;
pre=p; //保持pre指向p的前驱
InThreading(p->rchild); //右子树递归线索化
}
}//InThreading
//用算法5.8带头结点的中序线索化
void InOrderThreading (BiThrTree &Thrt,BiThrTree T)
{
//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
Thrt=new BiThrNode; //建头结点
Thrt->LTag=0; //头结点有左孩子,若树非空,则其左孩子为树根
Thrt->RTag=1; //头结点的右孩子指针为右线索
Thrt->rchild=Thrt; //初始化时右指针指向自己
if(!T) Thrt->lchild=Thrt; //若树为空,则左指针也指向自己
else
{
Thrt->lchild=T; pre=Thrt; //头结点的左孩子指向根,pre初值指向头结点
InThreading(T); //调用算法5.7,对以T为根的二叉树进行中序线索化
pre->rchild=Thrt; //算法5.7结束后,pre为最右结点,pre的右线索指向头结点
pre->RTag=1;
Thrt->rchild=pre; //头结点的右线索指向pre
}
} //InOrderThreading
void InOrderTraverse_Thr(BiThrTree T)
{
//T指向头结点,头结点的左链lchild指向根结点,可参见线索化算法5.8。
//中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出
BiThrTree p;
p=T->lchild; //p指向根结点
while(p!=T) //空树或遍历结束时,p==T
{
while(p->LTag==0) //沿左孩子向下
p=p->lchild; //访问其左子树为空的结点
cout<<p->data;
while(p->RTag==1&&p->rchild!=T)
{
p=p->rchild; //沿右线索访问后继结点
cout<<p->data;
}
p=p->rchild;
}
} //InOrderTraverse_Thr
void main()
{
pre->RTag=1;
pre->rchild=NULL;
BiThrTree tree,Thrt;
cout<<"请输入建立二叉链表的序列:\n";
CreateBiTree(tree);
InOrderThreading(Thrt,tree);
cout<<"中序遍历线索二叉树的结果为:\n";
InOrderTraverse_Thr(Thrt);
cout<<endl;
}

View File

@@ -0,0 +1,84 @@
//算法6.1 采用邻接矩阵表示法创建无向网
#include <iostream>
using namespace std;
#define MaxInt 32767 //表示极大值,即∞
#define MVNum 100 //最大顶点数
#define OK 1
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
//- - - - -图的邻接矩阵存储表示- - - - -
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
int LocateVex(AMGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
int CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt;
cout << "输入边依附的顶点及权值,如 a b 5" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
ArcType w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = w; //边<v1, v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
return OK;
}//CreateUDN
int main(){
cout << "************算法6.1 采用邻接矩阵表示法创建无向网**************" << endl << endl;
AMGraph G; int i , j;
CreateUDN(G);
cout <<endl;
cout << "*****邻接矩阵表示法创建的无向网*****" << endl;
for(i = 0 ; i < G.vexnum ; ++i){
for(j = 0; j < G.vexnum; ++j){
if(j != G.vexnum - 1){
if(G.arcs[i][j] != MaxInt)
cout << G.arcs[i][j] << "\t";
else
cout << "∞" << "\t";
}
else{
if(G.arcs[i][j] != MaxInt)
cout << G.arcs[i][j] <<endl;
else
cout << "∞" <<endl;
}
}
}//for
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,135 @@
//算法6.10 迪杰斯特拉算法
#include <iostream>
using namespace std;
#define MaxInt 32767 //表示极大值,即∞
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
int *D=new int[MVNum]; //用于记录最短路的长度
bool *S=new bool[MVNum]; //标记顶点是否进入S集合
int *Path=new int[MVNum]; //用于记录最短路顶点的前驱
//------------图的邻接矩阵-----------------
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
int LocateVex(AMGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称:,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt;
cout << "输入边依附的顶点及权值,如a b 7" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
ArcType w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = w; //边<v1, v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
void ShortestPath_DIJ(AMGraph G, int v0){
//用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径
int v , i , w , min;
int n = G.vexnum; //n为G中顶点的个数
for(v = 0; v < n; ++v){ //n个顶点依次初始化
S[v] = false; //S初始为空集
D[v] = G.arcs[v0][v]; //将v0到各个终点的最短路径长度初始化为弧上的权值
if(D[v] < MaxInt) Path [v] = v0; //如果v0和v之间有弧,则将v的前驱置为v0
else Path [v] = -1; //如果v0和v之间无弧,则将v的前驱置为-1
}//for
S[v0]=true; //将v0加入S
D[v0]=0; //源点到源点的距离为0
/*―初始化结束,开始主循环,每次求得v0到某个顶点v的最短路径,将v加到S集―*/
for(i = 1;i < n; ++i){ //对其余n-1个顶点,依次进行计算
min= MaxInt;
for(w = 0; w < n; ++w)
if(!S[w] && D[w] < min){ //选择一条当前的最短路径,终点为v
v = w;
min = D[w];
}//if
S[v]=true; //将v加入S
for(w = 0;w < n; ++w) //更新从v0出发到集合V?S上所有顶点的最短路径长度
if(!S[w] && (D[v] + G.arcs[v][w] < D[w])){
D[w] = D[v] + G.arcs[v][w]; //更新D[w]
Path [w] = v; //更改w的前驱为v
}//if
}//for
}//ShortestPath_DIJ
void DisplayPath(AMGraph G , int begin ,int temp ){
//显示最短路
if(Path[temp] != -1){
DisplayPath(G , begin ,Path[temp]);
cout << G.vexs[Path[temp]] << "-->";
}
}//DisplayPath
void main()
{
cout << "************算法6.10 迪杰斯特拉算法**************" << endl << endl;
AMGraph G;
int i , j ,num_start , num_destination;
VerTexType start , destination;
CreateUDN(G);
cout <<endl;
cout << "*****无向网G创建完成!*****" << endl;
for(i = 0 ; i < G.vexnum ; ++i){
for(j = 0; j < G.vexnum; ++j){
if(j != G.vexnum - 1){
if(G.arcs[i][j] != MaxInt)
cout << G.arcs[i][j] << "\t";
else
cout << "∞" << "\t";
}
else{
if(G.arcs[i][j] != MaxInt)
cout << G.arcs[i][j] <<endl;
else
cout << "∞" <<endl;
}
}
}//for
cout << endl;
cout << "请依次输入起始点、终点名称:";
cin >> start >> destination;
num_start = LocateVex(G , start);
num_destination = LocateVex(G , destination);
ShortestPath_DIJ(G , num_start);
cout << endl <<"最短路径为:";
DisplayPath(G , num_start , num_destination);
cout << G.vexs[num_destination]<<endl;
}//main

View File

@@ -0,0 +1,111 @@
//算法6.11 弗洛伊德算法
#include <iostream>
using namespace std;
#define MaxInt 32767 //表示极大值,即∞
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
int Path[MVNum][MVNum]; //最短路径上顶点vj的前一顶点的序号
int D[MVNum][MVNum]; //记录顶点vi和vj之间的最短路径长度
//------------图的邻接矩阵---------------
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
int LocateVex(AMGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建有向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i){ //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j){
if(j != i)
G.arcs[i][j] = MaxInt;
else
G.arcs[i][j] = 0;
}//for
}//for
cout << "输入边依附的顶点及权值,如a b 3" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
ArcType w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = w; //边<v1, v2>的权值置为w
}//for
}//CreateUDN
void ShortestPath_Floyed(AMGraph G){
//用Floyd算法求有向网G中各对顶点i和j之间的最短路径
int i , j , k ;
for (i = 0; i < G.vexnum; ++i) //各对结点之间初始已知路径及距离
for(j = 0; j < G.vexnum; ++j){
D[i][j] = G.arcs[i][j];
if(D[i][j] < MaxInt && i != j) Path[i][j]=i; //如果i和j之间有弧,则将j的前驱置为i
else Path [i][j] = -1; //如果i和j之间无弧,则将j的前驱置为-1
}//for
for(k = 0; k < G.vexnum; ++k)
for(i = 0; i < G.vexnum; ++i)
for(j = 0; j < G.vexnum; ++j)
if(D[i][k] + D[k][j] < D[i][j]){ //从i经k到j的一条路径更短
D[i][j] = D[i][k]+D[k][j]; //更新D[i][j]
Path[i][j] = Path[k][j]; //更改j的前驱为k
}//if
}//ShortestPath_Floyed
void DisplayPath(AMGraph G , int begin ,int temp ){
//显示最短路径
if(Path[begin][temp] != -1){
DisplayPath(G , begin ,Path[begin][temp]);
cout << G.vexs[Path[begin][temp]] << "-->";
}
}//DisplayPath
void main(){
cout << "************算法6.11 弗洛伊德算法**************" << endl << endl;
AMGraph G;
char start , destination;
int num_start , num_destination;
CreateUDN(G);
cout <<endl;
cout << "有向网G创建完成!" << endl;
ShortestPath_Floyed(G);
cout << "请依次输入路径的起点与终点的名称:";
cin >> start >> destination;
num_start = LocateVex(G , start);
num_destination = LocateVex(G , destination);
DisplayPath(G , num_start , num_destination);
cout << G.vexs[num_destination] << endl;
cout << "最短路径的长度为:" << D[num_start][num_destination] << endl;
cout <<endl;
}//main

View File

@@ -0,0 +1,186 @@
//算法6.12 拓扑排序
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
#define OK 1
#define ERROR 0
typedef char VerTexType;
//- - - - -图的邻接表存储表示- - - - -
typedef struct ArcNode{ //边结点
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
}ArcNode;
typedef struct VNode{
VerTexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct{
AdjList vertices; //邻接表
AdjList converse_vertices; //逆邻接表
int vexnum, arcnum; //图的当前顶点数和边数
}ALGraph;
//- - - - - - - - - - - - - - - -
//- - - - -顺序栈的定义- - - - -
typedef struct{
int *base;
int *top;
int stacksize;
}spStack;
//- - - - - - - - - - - - - - - -
int indegree[MVNum]; //数组indegree存放个顶点的入度
spStack S;
//------------栈的相关操作----------------------
void InitStack(spStack &S){
//初始化栈
S.base = new int[MVNum];
if(!S.base)
exit(1);
S.top = S.base;
S.stacksize = MVNum;
}//InitStack
void Push(spStack &S , int i){
//进栈
if(S.top - S.base == S.stacksize)
return;
*S.top++ = i;
}//Push
void Pop(spStack &S , int &i){
//出栈
if(S.top == S.base)
return;
i = *--S.top;
}//Pop
bool StackEmpty(spStack S){
//判断栈是否为空
if(S.top == S.base)
return true;
return false;
}//StackEmpty
//-------------------------------------------------
int LocateVex(ALGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vertices[i].data == v)
return i;
return -1;
}//LocateVex
int CreateUDG(ALGraph &G){
//创建有向图G的邻接表、逆邻接表
int i , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){ //输入各点,构造表头结点表
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vertices[i].data; //输入顶点值
G.converse_vertices[i].data = G.vertices[i].data;
//初始化表头结点的指针域为NULL
G.vertices[i].firstarc=NULL;
G.converse_vertices[i].firstarc=NULL;
}//for
cout << endl;
cout << "输入边依附的顶点,如a b" << endl;
for(k = 0; k < G.arcnum;++k){ //输入各边,构造邻接表
VerTexType v1 , v2;
int i , j;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的两个顶点
i = LocateVex(G, v1); j = LocateVex(G, v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex=j; //邻接点序号为j
p1->nextarc = G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=new ArcNode; //生成一个新的边结点*p1
p2->adjvex=i; //逆邻接点序号为i
p2->nextarc = G.converse_vertices[j].firstarc; G.converse_vertices[j].firstarc=p2;
//将新结点*p1插入顶点vi的边表头部
}//for
return OK;
}//CreateUDG
void FindInDegree(ALGraph G){
//求出各顶点的入度存入数组indegree中
int i , count;
for(i = 0 ; i < G.vexnum ; i++){
count = 0;
ArcNode *p = G.converse_vertices[i].firstarc;
if(p){
while(p){
p = p->nextarc;
count++;
}
}
indegree[i] = count;
}
}//FindInDegree
int TopologicalSort(ALGraph G , int topo[]){
//有向图G采用邻接表存储结构
//若G无回路,则生成G的一个拓扑序列topo[]并返回OK,否则ERROR
int i , m;
FindInDegree(G); //求出各顶点的入度存入数组indegree中
InitStack(S); //栈S初始化为空
for(i = 0; i < G.vexnum; ++i)
if(!indegree[i]) Push(S, i); //入度为0者进栈
m = 0; //对输出顶点计数,初始为0
while(!StackEmpty(S)){ //栈S非空
Pop(S, i); //将栈顶顶点vi出栈
topo[m]=i; //将vi保存在拓扑序列数组topo中
++m; //对输出顶点计数
ArcNode *p = G.vertices[i].firstarc; //p指向vi的第一个邻接点
while(p){
int k = p->adjvex; //vk为vi的邻接点
--indegree[k]; //vi的每个邻接点的入度减1
if(indegree[k] ==0) Push(S, k); //若入度减为0,则入栈
p = p->nextarc; //p指向顶点vi下一个邻接结点
}//while
}//while
if(m < G.vexnum) return ERROR; //该有向图有回路
else return OK;
}//TopologicalSort
int main(){
cout << "************算法6.12 拓扑排序**************" << endl << endl;
ALGraph G;
CreateUDG(G);
int *topo = new int [G.vexnum];
cout << endl;
cout << "有向图的邻接表、逆邻接表创建完成!" << endl << endl;
if(TopologicalSort(G , topo)){
cout << "该有向图的拓扑有序序列为:";
for(int j = 0 ; j < G.vexnum; j++){
if(j != G.vexnum - 1)
cout << G.vertices[topo[j]].data << " , ";
else
cout << G.vertices[topo[j]].data << endl << endl;
}//for
}
else
cout << "网中存在环,无法进行拓扑排序!" <<endl << endl;
return OK;
}//main

View File

@@ -0,0 +1,242 @@
//算法6.13 关键路径算法
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
#define BDNum MVNum * (MVNum - 1) //最大边数
#define OK 1
#define ERROR 0
typedef char VerTexType;
//- - - - -图的邻接表存储表示- - - - -
typedef struct ArcNode{ //边结点
int adjvex; //该边所指向的顶点的位置
int weight; //权值
struct ArcNode *nextarc; //指向下一条边的指针
}ArcNode;
typedef struct VNode{
VerTexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct{
AdjList vertices; //邻接表
AdjList converse_vertices; //逆邻接表
int vexnum, arcnum; //图的当前顶点数和边数
}ALGraph;
//- - - - - - - - - - - - - - - -
//- - - - -顺序栈的定义- - - - -
typedef struct{
int *base;
int *top;
int stacksize;
}spStack;
//- - - - - - - - - - - - - - - -
int indegree[MVNum]; //数组indegree存放个顶点的入度
int ve[BDNum]; //事件vi的最早发生时间
int vl[BDNum]; //事件vi的最迟发生时间
int topo[MVNum]; //记录拓扑序列的顶点序号
spStack S;
//----------------栈的操作--------------------
void InitStack(spStack &S){
//栈的初始化
S.base = new int[MVNum];
if(!S.base)
exit(1);
S.top = S.base;
S.stacksize = MVNum;
}//InitStack
void Push(spStack &S , int i){
//入栈
if(S.top - S.base == S.stacksize)
return;
*S.top++ = i;
}//Push
void Pop(spStack &S , int &i){
//出栈
if(S.top == S.base)
return;
i = *--S.top;
}//Pop
bool StackEmpty(spStack S){
//判断栈是否为空
if(S.top == S.base)
return true;
return false;
}//StackEmpty
//---------------------------------------
int LocateVex(ALGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vertices[i].data == v)
return i;
return -1;
}//LocateVex
int CreateUDG(ALGraph &G){
//创建有向图G的邻接表、逆邻接表
int i , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){ //输入各点,构造表头结点表
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vertices[i].data; //输入顶点值
G.converse_vertices[i].data = G.vertices[i].data;
//初始化表头结点的指针域为NULL
G.vertices[i].firstarc=NULL;
G.converse_vertices[i].firstarc=NULL;
}//for
cout << endl;
cout << "输入边依附的顶点及其权值,如a b 3" << endl;
for(k = 0; k < G.arcnum;++k){ //输入各边,构造邻接表
VerTexType v1 , v2;
int i , j , w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及其权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的两个顶点
i = LocateVex(G, v1); j = LocateVex(G, v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex=j; //邻接点序号为j
p1->nextarc = G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
p1->weight = w;
//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=new ArcNode; //生成一个新的边结点*p1
p2->adjvex=i; //逆邻接点序号为i
p2->nextarc = G.converse_vertices[j].firstarc; G.converse_vertices[j].firstarc=p2;
p2->weight = w;
//将新结点*p1插入顶点vi的边表头部
}//for
return OK;
}//CreateUDG
void FindInDegree(ALGraph G){
//求出各顶点的入度存入数组indegree中
int i , count;
for(i = 0 ; i < G.vexnum ; i++){
count = 0;
ArcNode *p = G.converse_vertices[i].firstarc;
if(p){
while(p){
p = p->nextarc;
count++;
}
}//if
indegree[i] = count;
}//for
}//FindInDegree
int TopologicalOrder(ALGraph G , int topo[]){
//有向图G采用邻接表存储结构
//若G无回路,则生成G的一个拓扑序列topo[]并返回OK,否则ERROR
int i , m;
FindInDegree(G); //求出各顶点的入度存入数组indegree中
InitStack(S); //栈S初始化为空
for(i = 0; i < G.vexnum; ++i)
if(!indegree[i]) Push(S, i); //入度为0者进栈
m = 0; //对输出顶点计数,初始为0
while(!StackEmpty(S)){ //栈S非空
Pop(S, i); //将栈顶顶点vi出栈
topo[m]=i; //将vi保存在拓扑序列数组topo中
++m; //对输出顶点计数
ArcNode *p = G.vertices[i].firstarc; //p指向vi的第一个邻接点
while(p){
int k = p->adjvex; //vk为vi的邻接点
--indegree[k]; //vi的每个邻接点的入度减1
if(indegree[k] ==0) Push(S, k); //若入度减为0,则入栈
p = p->nextarc; //p指向顶点vi下一个邻接结点
}//while
}//while
if(m < G.vexnum) return ERROR; //该有向图有回路
else return OK;
}//TopologicalOrder
int CriticalPath(ALGraph G){
//G为邻接表存储的有向网,输出G的各项关键活动
int n , i , k , j , e , l;
if (!TopologicalOrder(G, topo)) return ERROR;
//调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环,返回ERROR
n = G.vexnum; //n为顶点个数
for(i = 0; i < n; i++) //给每个事件的最早发生时间置初值0
ve[i] = 0;
/*――――――――――按拓扑次序求每个事件的最早发生时间-――――-―――――*/
for(i = 0;i < n; i++){
k = topo[i]; //取得拓扑序列中的顶点序号k
ArcNode *p = G.vertices[k].firstarc; //p指向k的第一个邻接顶点
while(p != NULL){ //依次更新k的所有邻接顶点的最早发生时间
j = p->adjvex; //j为邻接顶点的序号
if(ve[j] < ve[k] + p->weight) //更新顶点j的最早发生时间ve[j]
ve[j] = ve[k] + p->weight;
p = p->nextarc; //p指向k的下一个邻接顶点
} //while
} //for
for(i=0;i<n;i++) //给每个事件的最迟发生时间置初值ve[n-1]
vl[i]=ve[n-1];
/*――――――――――按逆拓扑次序求每个事件的最迟发生时间-――――-―――――*/
for(i = n - 1;i >= 0; i--){
k = topo[i]; //取得拓扑序列中的顶点序号k
ArcNode *p = G.vertices[k].firstarc; //p指向k的第一个邻接顶点
while(p != NULL){ //根据k的邻接点,更新k的最迟发生时间
j = p->adjvex; //j为邻接顶点的序号
if(vl[k] > vl[j] - p->weight) //更新顶点k的最迟发生时间vl[k]
vl[k] = vl[j] - p->weight;
p = p->nextarc; //p指向k的下一个邻接顶点
}//while
}//for
/*――――――――――――判断每一活动是否为关键活动-――――――-―――――*/
cout << endl;
cout << "关键活动路径为:";
for(i = 0;i < n; i++){ //每次循环针对vi为活动开始点的所有活动
ArcNode *p = G.vertices[i].firstarc; //p指向i的第一个邻接顶点
while(p != NULL) {
j = p->adjvex; //j为i的邻接顶点的序号
e = ve[i]; //计算活动<vi, vj>的最早开始时间
l = vl[j] - p->weight; //计算活动<vi, vj>的最迟开始时间
if(e == l) //若为关键活动,则输出<vi, vj>
cout << G.vertices[i].data << "-->" << G.vertices[j].data << " ";
p = p->nextarc; //p指向i的下一个邻接顶点
} //while
} //for
return OK;
}//CriticalPath
int main(){
cout << "************算法6.13 关键路径算法**************" << endl << endl;
ALGraph G;
CreateUDG(G);
int *topo = new int [G.vexnum];
cout << endl;
cout << "有向图创建完成!" << endl << endl;
if(!CriticalPath(G))
cout << "网中存在环,无法进行拓扑排序!" <<endl << endl;
cout << endl;
return OK;
}//main

View File

@@ -0,0 +1,143 @@
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
#define ll __int64
int n,m;
#define Mod 10
#define N 10010
#define M 1000010
struct Edge{ //存储边的结构体
int to;
int next;
};
struct Node{ //存储点的结构体
int id;
int step;
};
struct sqQueue{ //队列的结构体
Node *base;
int front;
int rear;
};
Edge edge[N]; //
int head[N];
int vis[N];
int cnt;
sqQueue Q;
void Init(){
memset(head,-1,sizeof head);
cnt=0;
}
void addEdge(int u,int v){ //添加边
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void InitQueue(sqQueue &Q){ //初始化队列
Q.base = new Node[M];
if(!Q.base)
exit(OVERFLOW);
Q.front = Q.rear = 0;
return;
}
int QueueLength(sqQueue Q){ //求队列的长度
return(Q.rear-Q.front+M)%M;
}
int EnQueue(sqQueue &Q,Node e){ //入队
if((Q.rear+1)%M == Q.front)
return 0;
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1)%M;
return 1;
}
int DeQueue(sqQueue &Q){ //出队
if(Q.front == Q.rear)
return 0;
Q.front = (Q.front+1)%M;
return 1;
}
Node getHead(sqQueue Q){ //得到队列头部的元素
return Q.base[Q.front];
}
void bfs(){ //用bfs来搜索与初始点距离不超过7的点的个数占总数的百分比
memset(vis,0,sizeof vis);
InitQueue(Q);
Node cur,next;
cur.id = 0;
cur.step = 0;
EnQueue(Q,cur);
vis[0] = 1;
int num = 0;
while(QueueLength(Q)){
cur = getHead(Q);
DeQueue(Q);
if(cur.step>7){
break;
}
num++;
int s = cur.id;
for(int p = head[s];p!=-1;p=edge[p].next){
int v = edge[p].to;
if(!vis[v]){
next.id = v;
next.step = cur.step + 1;
vis[v] = 1;
EnQueue(Q,next);
}
}
}
printf("%.4f\n",num*1.0/n);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
while(sfd(n,m)!=EOF){ //n为顶点的数量,m为边的数量,点的编号从0-n-1
Init(); //初始化
int u,v;
for(int i=0;i<m;i++){
scanf("%d%d",&u,&v); //输入两个相邻的点
addEdge(u,v);
addEdge(v,u); //无向边
}
bfs();
}
return 0;
}

View File

@@ -0,0 +1,103 @@
//算法6.2 采用邻接表表示法创建无向图
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
#define OK 1
typedef char VerTexType; //顶点信息
typedef int OtherInfo; //和边相关的信息
//- - - - -图的邻接表存储表示- - - - -
typedef struct ArcNode{ //边结点
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
OtherInfo info; //和边相关的信息
}ArcNode;
typedef struct VNode{
VerTexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct{
AdjList vertices; //邻接表
int vexnum, arcnum; //图的当前顶点数和边数
}ALGraph;
int LocateVex(ALGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vertices[i].data == v)
return i;
return -1;
}//LocateVex
int CreateUDG(ALGraph &G){
//采用邻接表表示法,创建无向图G
int i , k;
cout <<"请输入总顶点数,总边数中间以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如 a " <<endl;
for(i = 0; i < G.vexnum; ++i){ //输入各点,构造表头结点表
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].firstarc=NULL; //初始化表头结点的指针域为NULL
}//for
cout << endl;
cout << "请输入一条边依附的顶点,如 a b" << endl;
for(k = 0; k < G.arcnum;++k){ //输入各边,构造邻接表
VerTexType v1 , v2;
int i , j;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的两个顶点
i = LocateVex(G, v1); j = LocateVex(G, v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex=j; //邻接点序号为j
p1->nextarc= G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=new ArcNode; //生成另一个对称的新的边结点*p2
p2->adjvex=i; //邻接点序号为i
p2->nextarc= G.vertices[j].firstarc; G.vertices[j].firstarc=p2;
//将新结点*p2插入顶点vj的边表头部
}//for
return OK;
}//CreateUDG
int main(){
cout << "************算法6.2 采用邻接表表示法创建无向图**************" << endl << endl;
ALGraph G;
CreateUDG(G);
int i;
cout << endl;
cout << "*****邻接表表示法创建的无向图*****" << endl;
for(i = 0 ; i < G.vexnum ; ++i){
VNode temp = G.vertices[i];
ArcNode *p = temp.firstarc;
if(p == NULL){
cout << G.vertices[i].data;
cout << endl;
}
else{
cout << temp.data;
while(p){
cout << "->";
cout << p->adjvex;
p = p->nextarc;
}
}
cout << endl;
}
return 0;
}//main

View File

@@ -0,0 +1,114 @@
//算法6.3 深度优先搜索遍历连通图的递归算法
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}Graph;
bool visited[MVNum]; //访问标志数组,其初值为"false"
int FirstAdjVex(Graph G , int v); //返回v的第一个邻接点
int NextAdjVex(Graph G , int v , int w); //返回v相对于w的下一个邻接点
int LocateVex(Graph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(Graph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数 , 以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如 a:" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = 0;
cout << "输入边依附的顶点,如:a b" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[j][i] = G.arcs[i][j] = 1; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
void DFS(Graph G, int v){ //从第v个顶点出发递归地深度优先遍历图G
cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
int w;
for(w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))
//依次检查v的所有邻接点w ,FirstAdjVex(G, v)表示v的第一个邻接点
//NextAdjVex(G, v, w)表示v相对于w的下一个邻接点,w≥0表示存在邻接点
if(!visited[w]) DFS(G, w); //对v的尚未访问的邻接顶点w递归调用DFS
}//DFS
int FirstAdjVex(Graph G , int v){
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//FirstAdjVex
int NextAdjVex(Graph G , int v , int w){
int i;
for(i = w ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//NextAdjVex
int main(){
cout << "************算法6.3 深度优先搜索遍历连通图的递归算法**************" << endl << endl;
Graph G;
CreateUDN(G);
cout << endl;
cout << "无向连通图G创建完成!" << endl << endl;
cout << "请输入遍历连通图的起始点:";
VerTexType c;
cin >> c;
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
cout << endl;
while(i >= G.vexnum){
cout << "该点不存在,请重新输入!" << endl;
cout << "请输入遍历连通图的起始点:";
cin >> c;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
}
cout << "深度优先搜索遍历连通图结果:" << endl;
DFS(G , i);
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,105 @@
//算法6.4 深度优先搜索遍历非连通图
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
//-------------图的邻接矩阵-----------------
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}Graph;
bool visited[MVNum]; //访问标志数组,其初值为"false"
int FirstAdjVex(Graph G , int v); //返回v的第一个邻接点
int NextAdjVex(Graph G , int v , int w); //返回v相对于w的下一个邻接点
int LocateVex(Graph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(Graph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = 0;
cout << "输入边依附的顶点,如a b" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[j][i] = G.arcs[i][j] = 1; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
void DFS(Graph G, int v){
//从第v个顶点出发递归地深度优先遍历图G
cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
int w;
for(w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))
//依次检查v的所有邻接点w ,FirstAdjVex(G, v)表示v的第一个邻接点
//NextAdjVex(G, v, w)表示v相对于w的下一个邻接点,w≥0表示存在邻接点
if(!visited[w]) DFS(G, w); //对v的尚未访问的邻接顶点w递归调用DFS
}//DFS
void DFSTraverse(Graph G){
//对非连通图G做深度优先遍历
int v;
for(v = 0; v < G.vexnum; ++v) visited[v] = false; //访问标志数组初始化
for(v = 0; v < G.vexnum; ++v) //循环调用算法6.3
if(!visited[v]) DFS(G, v); //对尚未访问的顶点调用DFS
}//DFSTraverse
int FirstAdjVex(Graph G , int v){
//返回v的第一个邻接点
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//FirstAdjVex
int NextAdjVex(Graph G , int v , int w){
//返回v相对于w的下一个邻接点
int i;
for(i = w ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//NextAdjVex
int main(){
cout << "************算法6.4 深度优先搜索遍历非连通图**************" << endl << endl;
Graph G;
CreateUDN(G);
cout << endl;
cout << "无向图G创建完成!" << endl << endl;
cout << "深度优先搜索遍历非连通图结果:" << endl;
DFSTraverse(G);
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,116 @@
//算法6.5 采用邻接矩阵表示图的深度优先搜索遍历
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
//------------图的邻接矩阵------------------
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}Graph;
bool visited[MVNum]; //访问标志数组,其初值为"false"
int FirstAdjVex(Graph G , int v); //返回v的第一个邻接点
int NextAdjVex(Graph G , int v , int w); //返回v相对于w的下一个邻接点
int LocateVex(Graph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(Graph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" <<endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = 0;
cout << "输入边依附的顶点,如a b" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[j][i] = G.arcs[i][j] = 1; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
void DFS(Graph G, int v){
//图G为邻接矩阵类型
int w;
cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
for(w = 0; w < G.vexnum; w++) //依次检查邻接矩阵v所在的行
if((G.arcs[v][w] != 0)&& (!visited[w])) DFS(G, w); //G.arcs[v][w]!=0表示w是v的邻接点,如果w未访问,则递归调用DFS
}//DFS
int FirstAdjVex(Graph G , int v){
//返回v的第一个邻接点
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//FirstAdjVex
int NextAdjVex(Graph G , int v , int w){
//返回v相对于w的下一个邻接点
int i;
for(i = w ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//NextAdjVex
int main(){
cout << "************算法6.5 采用邻接矩阵表示图的深度优先搜索遍历**************" << endl << endl;
Graph G;
CreateUDN(G);
cout << endl;
cout << "无向图G创建完成!" << endl << endl;
cout << "请输入遍历无向图G的起始点:";
VerTexType c;
cin >> c;
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
cout << endl;
while(i >= G.vexnum){
cout << "该点不存在,请重新输入!" << endl;
cout << "请输入遍历连通图的起始点:";
cin >> c;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
}
cout << "深度优先搜索遍历无向图G结果:" << endl;
DFS(G , i);
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,117 @@
//算法6.6 采用邻接表表示图的深度优先搜索遍历
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
typedef char VerTexType; //假设顶点的数据类型为字符型
//-------------图的邻接表---------------------
typedef struct ArcNode{ //边结点
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
}ArcNode;
typedef struct VNode{
VerTexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型
typedef struct{
AdjList vertices; //邻接表
int vexnum, arcnum; //图的当前顶点数和边数
}ALGraph;
bool visited[MVNum]; //访问标志数组,其初值为"false"
int LocateVex(ALGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vertices[i].data == v)
return i;
return -1;
}//LocateVex
void CreateUDG(ALGraph &G){
//采用邻接表表示法,创建无向图G
int i , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){ //输入各点,构造表头结点表
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vertices[i].data; //输入顶点值
G.vertices[i].firstarc=NULL; //初始化表头结点的指针域为NULL
}//for
cout << endl;
cout << "输入边依附的顶点,如a b" << endl;
for(k = 0; k < G.arcnum;++k){ //输入各边,构造邻接表
VerTexType v1 , v2;
int i , j;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的两个顶点
i = LocateVex(G, v1); j = LocateVex(G, v2);
//确定v1和v2在G中位置,即顶点在G.vertices中的序号
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex=j; //邻接点序号为j
p1->nextarc= G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=new ArcNode; //生成另一个对称的新的边结点*p2
p2->adjvex=i; //邻接点序号为i
p2->nextarc= G.vertices[j].firstarc; G.vertices[j].firstarc=p2;
//将新结点*p2插入顶点vj的边表头部
}//for
}//CreateUDG
void DFS(ALGraph G, int v){ //图G为邻接表类型
cout << G.vertices[v].data << " ";
visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
ArcNode *p = G.vertices[v].firstarc; //p指向v的边链表的第一个边结点
while(p != NULL){ //边结点非空
int w = p->adjvex; //表示w是v的邻接点
if(!visited[w]) DFS(G, w); //如果w未访问,则递归调用DFS
p = p->nextarc; //p指向下一个边结点
}
}//DFS
int main(){
cout << "************算法6.6 采用邻接表表示图的深度优先搜索遍历**************" << endl << endl;
ALGraph G;
CreateUDG(G);
cout << endl;
cout << "无向连通图G创建完成!" << endl << endl;
cout << "请输入遍历连通图的起始点:";
VerTexType c;
cin >> c;
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vertices[i].data)
break;
}
cout << endl;
while(i >= G.vexnum){
cout << "该点不存在,请重新输入!" << endl;
cout << "请输入遍历连通图的起始点:";
cin >> c;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vertices[i].data)
break;
}
}
cout << "深度优先搜索遍历图结果:" << endl;
DFS(G , i);
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,163 @@
//算法6.7 广度优先搜索遍历连通图
#include <iostream>
using namespace std;
#define MVNum 100 //最大顶点数
#define MAXQSIZE 100 //最大队列长度
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
bool visited[MVNum]; //访问标志数组,其初值为"false"
//-----图的邻接矩阵存储表示-----
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}Graph;
//----队列的定义及操作--------
typedef struct{
ArcType *base; //初始化的动态分配存储空间
int front; //头指针,若队列不空,指向队头元素
int rear; //尾指针,若队列不空,指向队尾元素的下一个位置
}sqQueue;
void InitQueue(sqQueue &Q){
//构造一个空队列Q
Q.base = new ArcType[MAXQSIZE];
if(!Q.base) exit(1); //存储分配失败
Q.front = Q.rear = 0;
}//InitQueue
void EnQueue(sqQueue &Q, ArcType e){
//插入元素e为Q的新的队尾元素
if((Q.rear + 1) % MAXQSIZE == Q.front)
return;
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
}//EnQueue
bool QueueEmpty(sqQueue Q){
//判断是否为空队
if(Q.rear == Q.front)
return true;
return false;
}//QueueEmpty
void DeQueue(sqQueue &Q, ArcType &u){
//队头元素出队并置为u
u = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
}//DeQueue
//--------------------------------------------------
int LocateVex(Graph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(Graph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = 0;
cout << "输入边依附的顶点,如a b" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2; //输入一条边依附的顶点
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = 1; //边<v1, v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
int FirstAdjVex(Graph G , int v){
//返回v的第一个邻接点
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(G.arcs[v][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//FirstAdjVex
int NextAdjVex(Graph G , int u , int w){
//返回v相对于w的下一个邻接点
int i;
for(i = w ; i < G.vexnum ; ++i){
if(G.arcs[u][i] == 1 && visited[i] == false)
return i;
}
return -1;
}//NextAdjVex
void BFS (Graph G, int v){
//按广度优先非递归遍历连通图G
sqQueue Q;
ArcType u;
ArcType w;
cout << G.vexs[v] << " "; visited[v] = true; //访问第v个顶点,并置访问标志数组相应分量值为true
InitQueue(Q); //辅助队列Q初始化,置空
EnQueue(Q, v); //v进队
while(!QueueEmpty(Q)){ //队列非空
DeQueue(Q, u); //队头元素出队并置为u
for(w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w)){
//依次检查u的所有邻接点w ,FirstAdjVex(G, u)表示u的第一个邻接点
//NextAdjVex(G, u, w)表示u相对于w的下一个邻接点,w≥0表示存在邻接点
if(!visited[w]){ //w为u的尚未访问的邻接顶点
cout << G.vexs[w] << " "; visited[w] = true; //访问w,并置访问标志数组相应分量值为true
EnQueue(Q, w); //w进队
}//if
}//for
}//while
}//BFS
int main(){
cout << "************算法6.7 广度优先搜索遍历连通图**************" << endl << endl;
Graph G;
CreateUDN(G);
cout << endl;
cout << "无向连通图G创建完成!" << endl << endl;
cout << "请输入遍历连通图的起始点:";
VerTexType c;
cin >> c;
int i;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
cout << endl;
while(i >= G.vexnum){
cout << "该点不存在,请重新输入!" << endl;
cout << "请输入遍历连通图的起始点:";
cin >> c;
for(i = 0 ; i < G.vexnum ; ++i){
if(c == G.vexs[i])
break;
}
}
cout << "深度优先搜索遍历连通图结果:" << endl;
BFS(G , i);
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,115 @@
//算法6.8 普里姆算法
#include <iostream>
using namespace std;
typedef char VerTexType;
typedef int ArcType;
#define MVNum 100
#define MaxInt 32767 //表示极大值,即∞
//辅助数组的定义,用来记录从顶点集U到V-U的权值最小的边
struct{
VerTexType adjvex; //最小边在U中的那个顶点
ArcType lowcost; //最小边上的权值
}closedge[MVNum];
//- - - - -图的邻接表存储表示- - - - -
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
int LocateVex(AMGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt;
cout << "输入边依附的顶点及权值,如a b 5" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
ArcType w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = w; //边<v1, v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
}//for
}//CreateUDN
int Min(AMGraph G){
//返回权值最小的点
int i;
int index = -1;
int min = MaxInt;
for(i = 0 ; i < G.vexnum ; ++i){
if(min > closedge[i].lowcost && closedge[i].lowcost != 0){
min = closedge[i].lowcost;
index = i;
}
}//for
return index;
}//Min
void MiniSpanTree_Prim(AMGraph G, VerTexType u){
//无向网G以邻接矩阵形式存储,从顶点u出发构造G的最小生成树T,输出T的各条边
int k , j , i;
VerTexType u0 , v0;
k =LocateVex(G, u); //k为顶点u的下标
for(j = 0; j < G.vexnum; ++j){ //对V-U的每一个顶点vi,初始化closedge[i]
if(j != k){
closedge[j].adjvex = u;
closedge[j].lowcost = G.arcs[k][j]; //{adjvex, lowcost}
}//if
}//for
closedge[k].lowcost = 0; //初始,U = {u}
for(i = 1; i < G.vexnum; ++i){ //选择其余n-1个顶点,生成n-1条边(n= G.vexnum)
k = Min(G);
//求出T的下一个结点:第k个顶点,closedge[k]中存有当前最小边
u0 = closedge[k].adjvex; //u0为最小边的一个顶点,u0∈U
v0 = G.vexs[k]; //v0为最小边的另一个顶点,v0∈V-U
cout << "边 " <<u0 << "--->" << v0 << endl; //输出当前的最小边(u0, v0)
closedge[k].lowcost = 0; //第k个顶点并入U集
for(j = 0; j < G.vexnum; ++j)
if(G.arcs[k][j] < closedge[j].lowcost){ //新顶点并入U后重新选择最小边
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j];
}//if
}//for
}//MiniSpanTree_Prim
int main(){
cout << "************算法6.8 普里姆算法**************" << endl << endl;
AMGraph G;
CreateUDN(G);
cout << endl;
cout << "无向图G创建完成!" << endl;
cout <<endl;
cout << "******利用普里姆算法构造最小生成树结果:******" << endl;
MiniSpanTree_Prim(G , 'a');
cout <<endl;
return 0;
}//main

View File

@@ -0,0 +1,125 @@
//算法6.9 克鲁斯卡尔算法
#include <iostream>
using namespace std;
typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType;
#define MVNum 100 //最大顶点数
#define MaxInt 32767 //表示极大值,即∞
//----------------图的邻接矩阵---------------------
typedef struct{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
//辅助数组Edges的定义
struct{
VerTexType Head; //边的始点
VerTexType Tail; //边的终点
ArcType lowcost; //边上的权值
}Edge[(MVNum * (MVNum - 1)) / 2];
int Vexset[MVNum]; //辅助数组Vexset的定义
int LocateVex(AMGraph G , VerTexType v){
//确定点v在G中的位置
for(int i = 0; i < G.vexnum; ++i)
if(G.vexs[i] == v)
return i;
return -1;
}//LocateVex
void CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建无向网G
int i , j , k;
cout <<"请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum; //输入总顶点数,总边数
cout << endl;
cout << "输入点的名称,如a" << endl;
for(i = 0; i < G.vexnum; ++i){
cout << "请输入第" << (i+1) << "个点的名称:";
cin >> G.vexs[i]; //依次输入点的信息
}
cout << endl;
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵,边的权值均置为极大值MaxInt
for(j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = MaxInt;
cout << "输入边依附的顶点及权值,如a b 6" << endl;
for(k = 0; k < G.arcnum;++k){ //构造邻接矩阵
VerTexType v1 , v2;
ArcType w;
cout << "请输入第" << (k + 1) << "条边依附的顶点及权值:";
cin >> v1 >> v2 >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, v1); j = LocateVex(G, v2); //确定v1和v2在G中的位置,即顶点数组的下标
G.arcs[i][j] = w; //边<v1, v2>的权值置为w
G.arcs[j][i] = G.arcs[i][j]; //置<v1, v2>的对称边<v2, v1>的权值为w
Edge[k].lowcost = w;
Edge[k].Head = v1;
Edge[k].Tail = v2;
}//for
}//CreateUDN
//----------冒泡排序-------------------
void Sort(AMGraph G){
int m = G.arcnum - 2;
int flag = 1;
while((m > 0) && flag == 1){
flag = 0;
for(int j = 0 ; j <= m ; j++){
if(Edge[j].lowcost > Edge[j+ 1].lowcost){
flag = 1;
VerTexType temp_Head = Edge[j].Head;
Edge[j].Head = Edge[j+ 1].Head;
Edge[j + 1].Head = temp_Head;
VerTexType temp_Tail = Edge[j].Tail;
Edge[j].Tail = Edge[j+ 1].Tail;
Edge[j + 1].Tail = temp_Tail;
ArcType temp_lowcost = Edge[j].lowcost;
Edge[j].lowcost = Edge[j+ 1].lowcost;
Edge[j + 1].lowcost = temp_lowcost;
}//if
}//for
--m;
}//while
}//Sort
void MiniSpanTree_Kruskal(AMGraph G){
//无向网G以邻接矩阵形式存储,构造G的最小生成树T,输出T的各条边
int i , j , v1 , v2 , vs1 , vs2;
Sort(G); //将数组Edge中的元素按权值从小到大排序
for(i = 0; i < G.vexnum; ++i) //辅助数组,表示各顶点自成一个连通分量
Vexset[i] = i;
for(i = 0; i < G.arcnum; ++i){
//依次查看排好序的数组Edge中的边是否在同一连通分量上
v1 =LocateVex(G, Edge[i].Head); //v1为边的始点Head的下标
v2 =LocateVex(G, Edge[i].Tail); //v2为边的终点Tail的下标
vs1 = Vexset[v1]; //获取边Edge[i]的始点所在的连通分量vs1
vs2 = Vexset[v2]; //获取边Edge[i]的终点所在的连通分量vs2
if(vs1 != vs2){ //边的两个顶点分属不同的连通分量
cout << Edge[i].Head << "-->" << Edge[i].Tail << endl; //输出此边
for(j = 0; j < G.vexnum; ++j) //合并vs1和vs2两个分量,即两个集合统一编号
if(Vexset[j] == vs2) Vexset[j] = vs1; //集合编号为vs2的都改为vs1
}//if
}//for
}//MiniSpanTree_Kruskal
void main(){
cout << "************算法6.9 克鲁斯卡尔算法**************" << endl << endl;
AMGraph G;
CreateUDN(G);
cout <<endl;
cout << "*****无向网G创建完成!*****" << endl;
cout <<endl;
MiniSpanTree_Kruskal(G);
}///main

View File

@@ -0,0 +1,67 @@
//算法7.1 顺序查找
#include<iostream>
using namespace std;
#define MAXSIZE 100
#define OK 1;
typedef struct{
int key;//关键字域
}ElemType;
typedef struct{
ElemType *R;
int length;
}SSTable;
int InitList_SSTable(SSTable &L)
{
L.R=new ElemType[MAXSIZE];
if (!L.R)
{
cout<<"初始化错误";
return 0;
}
L.length=0;
return OK;
}
int Insert_SSTable(SSTable &L)
{
int j=0;
for(int i=0;i<MAXSIZE;i++)
{
L.R[i].key=j;
L.length++;
j++;
}
return 1;
}
int Search_Seq(SSTable ST, int key){
//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为
//该元素在表中的位置,否则为0
for (int i=ST.length; i>=1; --i)
if (ST.R[i].key==key) return i; //从后往前找
return 0;
}// Search_Seq
void Show_End(int result,int testkey)
{
if(result==0)
cout<<"未找到"<<testkey<<endl;
else
cout<<"找到"<<testkey<<"位置为"<<result<<endl;
return;
}
void main()
{
SSTable ST;
InitList_SSTable(ST);
Insert_SSTable(ST);
int testkey1=7,testkey2=200;
int result;
result=Search_Seq(ST, testkey1);
Show_End(result,testkey1);
result=Search_Seq(ST, testkey2);
Show_End(result,testkey2);
}

View File

@@ -0,0 +1,58 @@
#include<iostream>
using namespace std;
//算法7.10 哈希表的查找
//- - - - -开放地址法哈希表的存储表示- - - - -
#define m 16 //哈希表的表长
#define NULLKEY 0 //单元为空的标记
struct HashTable{
int key; //关键字项
// InfoType otherinfo; //其他数据项
};
// 算法7.10为哈希表查找的算法,采用线性探测法处理冲突。
// 【算法实现】
int H(int key)
{
int result;
result=key%13;
return result;
}
int SearchHash(HashTable HT[],int key){
//在哈希表HT中查找关键字为key的元素,若查找成功,返回哈希表的单元标号,否则返回-1
int H0=H(key); //根据哈希函数H(key)计算哈希地址
int Hi;
if (HT[H0].key==NULLKEY) return -1; //若单元H0为空,则所查元素不存在
else if (HT[H0].key==key) return H0; //若单元H0中元素的关键字为key,则查找成功
else{
for(int i=1;i<m;++i){
Hi=(H0+i)%m; //按照线性探测法计算下一个哈希地址Hi
if (HT[Hi].key==NULLKEY) return -1; //若单元Hi为空,则所查元素不存在
else if (HT[Hi].key==key) return Hi; //若单元Hi中元素的关键字为key,则查找成功
}//for
return -1;
}//else
}//SearchHash
void main()
{
int result;
int a[16]={-1,14,1,68,27,55,19,20,84,79,23,11,10,-1.-1.-1};
HashTable HT[m];
for(int i=0;i<16;i++)
{
HT[i].key=a[i];
}
result=SearchHash(HT,55);
if(result!=-1)
{
cout<<"在第"<<result<<"位置找到"<<endl;
}
else
{
cout<<"未找到"<<endl;
}
}

View File

@@ -0,0 +1,66 @@
//算法7.2 设置监视哨的顺序查找
#include<iostream>
using namespace std;
#define MAXSIZE 100
#define OK 1;
typedef struct{
int key;//关键字域
}ElemType;
typedef struct{
ElemType *R;
int length;
}SSTable;
int InitList_SSTable(SSTable &L)
{
L.R=new ElemType[MAXSIZE];
if (!L.R)
{
cout<<"初始化错误";
return 0;
}
L.length=0;
return OK;
}
int Insert_SSTable(SSTable &L)
{
int j=1;//空出ST.R[0]的位置
for(int i=1;i<MAXSIZE;i++)
{
L.R[i].key=j;
L.length++;
j++;
}
return 1;
}
int Search_Seq(SSTable ST, int key){
//在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为
//该元素在表中的位置,否则为0
ST.R[0].key = key; //“哨兵”
for(int i = ST.length; ST.R[i].key!=key; --i) ; //从后往前找
return i;
}// Search_Seq
void Show_End(int result,int testkey)
{
if(result==0)
cout<<"未找到"<<testkey<<endl;
else
cout<<"找到"<<testkey<<"位置为"<<result<<endl;
return;
}
void main()
{
SSTable ST;
InitList_SSTable(ST);
Insert_SSTable(ST);
int testkey1=7,testkey2=200;
int result;
result=Search_Seq(ST, testkey1);
Show_End(result,testkey1);
result=Search_Seq(ST, testkey2);
Show_End(result,testkey2);
}

View File

@@ -0,0 +1,77 @@
//算法7.3 折半查找
#include<iostream>
using namespace std;
#define MAXSIZE 100
#define OK 1;
typedef struct{
int key;//关键字域
}ElemType;
typedef struct{
ElemType *R;
int length;
}SSTable;
int InitList_SSTable(SSTable &L)
{
L.R=new ElemType[MAXSIZE];
if (!L.R)
{
cout<<"初始化错误";
return 0;
}
L.length=0;
return OK;
}
int Insert_SSTable(SSTable &L)
{
int j=1;
for(int i=1;i<MAXSIZE;i++)
{
L.R[i].key=j;
L.length++;
j++;
}
return 1;
}
int Search_Bin(SSTable ST,int key) {
// 在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为
// 该元素在表中的位置,否则为0
int low=1,high=ST.length; //置查找区间初值
int mid;
while(low<=high) {
mid=(low+high) / 2;
if (key==ST.R[mid].key) return mid; //找到待查元素
else if (key<ST.R[mid].key) high = mid -1; //继续在前一子表进行查找
else low =mid +1; //继续在后一子表进行查找
}//while
return 0; //表中不存在待查元素
}// Search_Bin
void Show_End(int result,int testkey)
{
if(result==0)
cout<<"未找到"<<testkey<<endl;
else
cout<<"找到"<<testkey<<"位置为"<<result<<endl;
return;
}
void main()
{
SSTable ST;
InitList_SSTable(ST);
Insert_SSTable(ST);
int testkey1=7,testkey2=200;
int result;
result=Search_Bin(ST, testkey1);
Show_End(result,testkey1);
result=Search_Bin(ST, testkey2);
Show_End(result,testkey2);
}

View File

@@ -0,0 +1,134 @@
//算法7.4 二叉排序树的递归查找
//算法7.5 二叉排序树的插入
//算法7.6 二叉排序树的创建
//算法 7.7 二叉排序树的删除
#include<iostream>
using namespace std;
#define ENDFLAG '#'
//char a[10]={'5','6','7','2','1','9','8','10','3','4','#'};//全局变量
typedef struct ElemType{
char key;
}ElemType;
typedef struct BSTNode{
ElemType data; //结点数据域
BSTNode *lchild,*rchild; //左右孩子指针
}BSTNode,*BSTree;
//算法7.4 二叉排序树的递归查找
BSTree SearchBST(BSTree T,char key) {
//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
if((!T)|| key==T->data.key) return T; //查找结束
else if (key<T->data.key) return SearchBST(T->lchild,key); //在左子树中继续查找
else return SearchBST(T->rchild,key); //在右子树中继续查找
} // SearchBST
//算法7.5 二叉排序树的插入
void InsertBST(BSTree &T,ElemType e ) {
//当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
if(!T) { //找到插入位置,递归结束
BSTree S = new BSTNode; //生成新结点*S
S->data = e; //新结点*S的数据域置为e
S->lchild = S->rchild = NULL; //新结点*S作为叶子结点
T =S; //把新结点*S链接到已找到的插入位置
}
else if (e.key< T->data.key)
InsertBST(T->lchild, e ); //将*S插入左子树
else if (e.key> T->data.key)
InsertBST(T->rchild, e); //将*S插入右子树
}// InsertBST
//算法7.6 二叉排序树的创建
void CreateBST(BSTree &T ) {
//依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
T=NULL;
ElemType e;
cin>>e.key; //???
while(e.key!=ENDFLAG){ //ENDFLAG为自定义常量,作为输入结束标志
InsertBST(T, e); //将此结点插入二叉排序树T中
cin>>e.key; //???
}//while
}//CreatBST
void DeleteBST(BSTree &T,char key) {
//从二叉排序树T中删除关键字等于key的结点
BSTree p=T;BSTree f=NULL; //初始化
BSTree q;
BSTree s;
/*------------下面的while循环从根开始查找关键字等于key的结点*p-------------*/
while(p){
if (p->data.key == key) break; //找到关键字等于key的结点*p,结束循环
f=p; //*f为*p的双亲结点
if (p->data.key> key) p=p->lchild; //在*p的左子树中继续查找
else p=p->rchild; //在*p的右子树中继续查找
}//while
if(!p) return; //找不到被删结点则返回
/*―考虑三种情况实现p所指子树内部的处理:*p左右子树均不空、无右子树、无左子树―*/
if ((p->lchild)&& (p->rchild)) { //被删结点*p左右子树均不空
q = p;
s = p->lchild;
while (s->rchild) //在*p的左子树中继续查找其前驱结点,即最右下结点
{q = s; s = s->rchild;} //向右到尽头
p->data = s->data; //s指向被删结点的“前驱”
if(q!=p){
q->rchild = s->lchild; //重接*q的右子树
}
else q->lchild = s->lchild; //重接*q的左子树
delete s;
}//if
else{
if(!p->rchild) { //被删结点*p无右子树,只需重接其左子树
q = p; p = p->lchild;
}//else if
else if(!p->lchild) { //被删结点*p无左子树,只需重接其右子树
q = p; p = p->rchild;
}//else if
/*――――――――――将p所指的子树挂接到其双亲结点*f相应的位置――――――――*/
if(!f) T=p; //被删结点为根结点
else if (q==f->lchild) f->lchild = p; //挂接到*f的左子树位置
else f->rchild = p; //挂接到*f的右子树位置
delete q;
}
}//DeleteBST
//算法 7.7 二叉排序树的删除
//中序遍历
void InOrderTraverse(BSTree &T)
{
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data.key;
InOrderTraverse(T->rchild);
}
}
void main()
{
BSTree T;
cout<<"请输入若干字符,用回车区分,以#结束输入"<<endl;
CreateBST(T);
cout<<"当前有序二叉树中序遍历结果为"<<endl;
InOrderTraverse(T);
char key;//待查找或待删除内容
cout<<"请输入待查找字符"<<endl;
cin>>key;
BSTree result=SearchBST(T,key);
if(result)
{cout<<"找到字符"<<key<<endl;}
else
{cout<<"未找到"<<key<<endl;}
cout<<"请输入待删除的字符"<<endl;
cin>>key;
DeleteBST(T,key);
cout<<"当前有序二叉树中序遍历结果为"<<endl;
InOrderTraverse(T);
}

View File

@@ -0,0 +1,214 @@
//算法7.8 B-树的查找
//算法7.9 B-树的插入
#include<iostream>
using namespace std;
#define FALSE 0
#define TRUE 1
#define OK 1
#define m 3 //B-树的阶,暂设为3
typedef struct BTNode{
int keynum; //结点中关键字的个数,即结点的大小
BTNode *parent; //指向双亲结点
int key[m+1]; //关键字矢量,0号单元未用
BTNode *ptr[m+1]; //子树指针矢量
}BTNode,*BTree;
//- - - - - B-树的查找结果类型定义- - - - -
struct Result{
BTNode *pt; //指向找到的结点
int i; //1..m,在结点中的关键字序号
int tag; //1:查找成功,0:查找失败
};
int Search(BTree T,int key)
{
BTree p=T;
int endnum;
if(p) //树不为空时
{
endnum=p->keynum; //获得首节点包含的记录个数
}
else
{
return 0; //返回没找到
}
int i=0;
if(endnum==0)
{
return i; //树存在,但仅有一个为空根节点
}
else if(key>=p->key[endnum])//节点不为空,但当前值比最大的key还大
{
i=endnum;
return i;
}
else if(key<=p->key[1]) //节点不为空,但当前值比最小的key还小
{
return i;}
else
{
for(i=1;i<endnum;i++) //有合适的位置,即处于当前结点的最大和最小值之间,或找到了
{
if(p->key[i]<=key && key<p->key[i+1])
return i;
}
}
}
void Insert(BTree &q,int i,int x,BTree &ap)
{//将x插入q结点的i+1位置中
int j;
for(j=m-1;j>i;j--)
{
//将插入位置之后的key全部后移一位
q->key[j+1]=q->key[j];
}
for(j=m;j>i;j--)
{
//相应地也移动其后ptr的位置
q->ptr[j]=q->ptr[j-1];
}
q->key[i+1]=x;//插入x到该位置
q->ptr[i+1]=ap;
q->keynum++;
}
void split(BTree &q,int s,BTree &ap)
{ //将q->key[s+1,..,m], q->ptr[s+1,..,m]移入新结点*ap作为右结点
//原结点作为新的左侧结点
//中间值被保存在ap[0]->key中,等待找到跳转回InsertBTree()寻找到到合适的插入位置插入
int i;
ap=new BTNode;
for(i=s+1;i<=m;i++)
{ //将q->key[s+1,..,m]保存到ap->key[0,..,m-s+1]中
//将q->ptr[s+1,..,m]保存到ap->ptr[0,..,m-s+1]中
ap->key[i-s-1]=q->key[i];
ap->ptr[i-s-1]=q->ptr[i];
}
if(ap->ptr[0])
{
//当ap有子树的时候
for(i=0;i<=1;i++)
{
//将ap的子树的父亲改为ap自己
ap->ptr[i]->parent=ap;
}
}
ap->keynum=(m-s)-1;
ap->parent=q->parent;//将ap的父亲改为q的父亲
q->keynum=q->keynum-(m-s);//修改q的记录个数
}
void NewRoot(BTree &T,BTree q,int x,BTree &ap)//生成含信息(T, x, ap)的新的根结点*T,原T和ap为子树指针
{
BTree newT=new BTNode;//新建一个结点作为新的根
newT->key[1]=x;//写入新根的key[1]
newT->ptr[0]=T;//将原来的树根作为新根的左子树
newT->ptr[1]=ap;//ap作为新根的右子树
newT->keynum=1;
newT->parent=NULL;//新根的父亲为空
ap->parent=newT;//ap的父亲为新根
T->parent=newT;//T的父亲为新根
T=newT;//树改成新根引导的
}
//算法7.9 B-树的插入
int InsertBTree(BTree &T,int K,BTree q,int i){
int x=K;
BTree ap=NULL;
int finished=FALSE;//x表示新插入的关键字,ap为一个空指针
while(q&&!finished){
Insert(q,i,x,ap); //将x和ap分别插入到q->key[i+1]和q->ptr[i+1]
if (q->keynum<m)
finished=TRUE; //插入完成
else{ //分裂结点*q
int s= m/2;
split(q,s,ap);
x=ap->key[0];// x=q->key[s];
//将q->key[s+1..m], q->ptr[s..m]和q->recptr[s+1..m] 移入新结点*ap
q=q->parent;
if(q)
{
i=Search(q,x);
} //在双亲结点*q中查找x的插入位置
} //else
} //while
if(!finished) //T是空树(参数q初值为NULL)或者根结点已分裂为结点*q和*ap
NewRoot(T,q,x,ap); //生成含信息(T, x, ap)的新的根结点*T,原T和ap为子树指针
return OK;
} //InsertBTree //InsertBTree
//算法7.8 B-树的查找
Result SearchBTree(BTree &T, int key){
/*在m阶B-树T上查找关键字key,返回结果(pt,i,tag)。若查找成功,则特征值tag=1,指针pt所指结点中第i个关键字等于key;否则特征值tag=0,等于key的关键字应插入在指针pt所指结点中第i和第i+1个关键字之间*/
BTree p=T;
BTree q=NULL;
int found=FALSE;
int i=0; //初始化,p指向待查结点,q指向p的双亲
while(p&&!found){
i=Search(p,key);
//在p->key[1..keynum]中查找i,使得:p->key[i]<=key<p->key[i+1]
if(i>0&&p->key[i]==key)
found=TRUE; //找到待查关键字
else
{
q=p;
p=p->ptr[i];
}
}
Result result;
if(found)
{
result.pt=p;
result.i=i;
result.tag=1;
return result;
} //查找成功
else
{
result.pt=q;
result.i=i;
result.tag=0;
return result;
} //查找不成功,返回K的插入位置信息
}//SearchBTree
void InitialBTree(BTree &T)
{
//初始化一个空的根
T->keynum=0;
T->parent=NULL;
for(int i=0;i<m+1;i++)
{
T->ptr[i]=NULL;
}
}
void main()
{
BTree T=new BTNode;
InitialBTree(T);
//先用SearchBTree()找到要插入的位置,得到一个Result结构体
//再用InsertBTree()插入数据
Result result;
int a[11]={45,24,53,90,3,12,50,61,70,100};
for(int i=0;i<10;i++)
{
result=SearchBTree(T,a[i]);
if(result.tag==0)
{
InsertBTree(T,a[i],result.pt,result.i);
}
}
cout<<"OK";
}

View File

@@ -0,0 +1,65 @@
//算法8.1 直接插入排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
void InsertSort(SqList &L)
{
//对顺序表L做直接插入排序
int i,j;
for(i=2;i<=L.length;++i)
if(L.r[i].key<L.r[i-1].key)
{ //"<",需将r[i]插入有序子表
L.r[0]=L.r[i]; //将待插入的记录暂存到监视哨中
L.r[i]=L.r[i-1]; //r[i-1]后移
for(j=i-2; L.r[0].key<L.r[j].key;--j) //从后向前寻找插入位置
L.r[j+1]=L.r[j]; //记录逐个后移,直到找到插入位置
L.r[j+1]=L.r[0]; //将r[0]即原r[i],插入到正确位置
} //if
} //InsertSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
InsertSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,59 @@
//算法8.10 相邻两个有序子序列的归并
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}RedType;
void Create_Sq(RedType *R)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待合并的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=0;i<n;i++)
cin>>R[i].key;
}
void Merge(RedType R[],RedType T[],int low,int mid,int high)
{
//将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]
int i,j,k;
i=low; j=mid+1;k=low;
while(i<=mid&&j<=high)
{
//将R中记录由小到大地并入T中
if(R[i].key<=R[j].key) T[k++]=R[i++];
else T[k++]=R[j++];
}
while(i<=mid) //将剩余的R[low..mid]复制到T中
T[k++]=R[i++];
while(j<=high) //将剩余的R[j.high]复制到T中
T[k++]=R[j++];
}//Merge
void show(RedType *T,int low,int high)
{
int i;
for(i=low;i<=high;i++)
cout<<T[i].key<<endl;
}
void main()
{
RedType *R=new RedType[MAXSIZE];
RedType *T=new RedType[MAXSIZE];
Create_Sq(R);
int low,mid,high;
cout<<"请输入第一个有序子序列的起点、终点下标和第二个有序子序列的终点下标:\n";
cin>>low>>mid>>high;
Merge(R,T,low,mid,high);
cout<<"合并后的结果为:"<<endl;
show(T,low,high);
}

View File

@@ -0,0 +1,88 @@
//算法8.11 归并排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}RedType;
typedef struct
{
RedType *r;
int length;
}SqList;
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
//用算法8.10 相邻两个有序子序列的归并
void Merge(RedType R[],RedType T[],int low,int mid,int high)
{
//将有序表R[low..mid]和R[mid+1..high]归并为有序表T[low..high]
int i,j,k;
i=low; j=mid+1;k=low;
while(i<=mid&&j<=high)
{
//将R中记录由小到大地并入T中
if(R[i].key<=R[j].key) T[k++]=R[i++];
else T[k++]=R[j++];
}
while(i<=mid) //将剩余的R[low..mid]复制到T中
T[k++]=R[i++];
while(j<=high) //将剩余的R[j.high]复制到T中
T[k++]=R[j++];
}//Merge
void MSort(RedType R[],RedType T[],int low,int high)
{
//R[low..high]归并排序后放入T[low..high]中
int mid;
RedType *S=new RedType[MAXSIZE];
if(low==high) T[low]=R[low];
else
{
mid=(low+high)/2; //将当前序列一分为二,求出分裂点mid
MSort(R,S,low,mid); //对子序列R[low..mid] 递归归并排序,结果放入S[low..mid]
MSort(R,S,mid+1,high); //对子序列R[mid+1..high] 递归归并排序,结果放入S[mid+1..high]
Merge(S,T,low,mid,high); //将S[low..mid]和S [mid+1..high]归并到T[low..high]
}//else
}// MSort
void MergeSort(SqList &L)
{
//对顺序表L做归并排序
MSort(L.r,L.r,1,L.length);
}//MergeSort
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList R;
R.r=new RedType[MAXSIZE+1];
R.length=0;
Create_Sq(R);
MergeSort(R);
cout<<"排序后的结果为:"<<endl;
show(R);
}

View File

@@ -0,0 +1,173 @@
//算法8.12 基数排序
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define MAXNUM_KEY 8 //关键字项数的最大值
#define RADIX 10 //关键字基数,此时是十进制整数的基数
#define MAX_SPACE 10000
typedef char KeysType; //定义关键字类型为字符型
typedef int InfoType; //定义其它数据项的类型
typedef struct
{
KeysType keys[MAXNUM_KEY]; //关键字
InfoType otheritems; //其他数据项
int next;
}SLCell; //静态链表的结点类型
typedef struct
{
SLCell r[MAX_SPACE]; //静态链表的可利用空间,r[0]为头结点
int keynum; //记录的当前关键字个数
int recnum; //静态链表的当前长度
}SLList; //静态链表类型
typedef int ArrType[RADIX]; //指针数组类型
void InitList(SLList *L)
{
//初始化静态链表L(把数组D中的数据存于L中)
char c[MAXNUM_KEY],c1[MAXNUM_KEY];
int i,j,n,max; //max为关键字的最大值
max=-10000;
cout<<"请输入数据个数,不超过"<<MAX_SPACE<<"个。\n";
cin>>n;
while(n>MAX_SPACE)
{
cout<<"您输入的个数超过上限,请重新输入,不超过"<<MAX_SPACE<<"个。\n";
cin>>n;
}
int *D=new int[n];
cout<<"请输入"<<n<<"个排排序的数据:\n";
for(i=0;i<n;i++)
{
cin>>D[i];
if(max<D[i])
max=D[i];
}
(*L).keynum=(int)(ceil(log10(max)));
(*L).recnum=n;
for(i=1;i<=n;i++)
{
itoa(D[i-1],c,10); //将10进制整型转化为字符型,存入c
for(j=strlen(c);j<(*L).keynum;j++) //若c的长度<max的位数,在c前补'0'
{
strcpy(c1,"0");
strcat(c1,c);
strcpy(c,c1);
}
for(j=0;j<(*L).keynum;j++)
(*L).r[i].keys[j]=c[(*L).keynum-1-j];
}
}
int ord(char c)
{
//返回k的映射(个位整数)
return c-'0';
}
void Distribute(SLCell *r,int i,ArrType &f,ArrType &e)
{
//静态链表L的r域中记录已按(keys[0], …, keys[i-1])有序
//本算法按第i个关键字keys[i]建立RADIX个子表,使同一子表中记录的keys[i]相同。
//f[0..RADIX-1]和e[0..RADIX-1]分别指向各子表中第一个和最后一个记录
int j,p;
for(j=0;j<RADIX;++j) f[j]=0; //各子表初始化为空表
for(p=r[0].next;p;p=r[p].next)
{
j=ord(r[p].keys[i]); //ord将记录中第i个关键字映射到[0..RADIX-1]
if(!f[j]) f[j]=p;
else r[e[j]].next=p;
e[j]=p; //将p所指的结点插入第j个子表中
}//for
}//Distribute
int succ(int i)
{
//求后继函数
return ++i;
}
void Collect (SLCell *r,int i,ArrType &f,ArrType &e)
{
//本算法按keys[i]自小至大地将f[0..RADIX-1]所指各子表依次链接成一个链表
//e[0..RADIX-1]为各子表的尾指针
int j,t;
for(j=0;!f[j];j=succ(j)); //找第一个非空子表,succ为求后继函数
r[0].next=f[j];t=e[j]; //r[0].next指向第一个非空子表中第一个结点
while(j<RADIX-1)
{
for(j=succ(j);j<RADIX-1&&!f[j];j=succ(j)) ; //找下一个非空子表
if(f[j]) {r[t].next=f[j];t=e[j];} //链接两个非空子表
}//while
r[t].next=0; //t指向最后一个非空子表中的最后一个结点
}//Collect
void RadixSort(SLList &L)
{
//L是采用静态链表表示的顺序表
//对L做基数排序,使得L成为按关键字自小到大的有序静态链表,L.r[0]为头结点
int i;
ArrType f,e;
for(i=0;i<L.recnum;++i) L.r[i].next=i+1;
L.r[L.recnum].next = 0; //将L改造为静态链表
for(i=0;i<L.keynum;++i)
{
//按最低位优先依次对各关键字进行分配和收集
Distribute(L.r,i,f,e); //第i趟分配
Collect(L.r,i,f,e); //第i趟收集
}//for
} // RadixSort
void print(SLList L)
{
//按数组序号输出静态链表
int i,j;
for(i=1;i<=L.recnum;i++)
{
for(j=L.keynum-1;j>=0;j--)
cout<<L.r[i].keys[j];
cout<<endl;
}
}
void Sort(SLList L,int adr[])
{
//求得adr[1..L.length],adr[i]为静态链表L的第i个最小记录的序号
int i=1,p=L.r[0].next;
while(p)
{
adr[i++]=p;
p=L.r[p].next;
}
}
void Rearrange(SLList *L,int adr[])
{
//adr给出静态链表L的有序次序,即L.r[adr[i]]是第i小的记录。
//本算法按adr重排L.r,使其有序。算法10.18(L的类型有变)
int i,j,k;
if(adr[i]!=i)
{
j=i;
(*L).r[0]=(*L).r[i]; //暂存记录(*L).r[i]
while(adr[j]!=i)
{
//调整(*L).r[adr[j]]的记录到位直到adr[j]=i为止
k=adr[j];
(*L).r[j]=(*L).r[k];
adr[j]=j;
j=k; //记录按序到位
}
(*L).r[j]=(*L).r[0];
adr[j]=j;
}
}
void main()
{
SLList l;
int *adr;
InitList(&l);
RadixSort(l);
adr=new int[l.recnum];
Sort(l,adr);
Rearrange(&l,adr);
cout<<"排序后(重排记录):\n";
print(l);
}

View File

@@ -0,0 +1,69 @@
//算法8.2 折半插入排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表
void BInsertSort(SqList &L){
//对顺序表L做折半插入排序
int i,j,low,high,m;
for(i=2;i<=L.length;++i)
{
L.r[0]=L.r[i]; //将待插入的记录暂存到监视哨中
low=1; high=i-1; //置查找区间初值
while(low<=high)
{ //在r[low..high]中折半查找插入的位置
m=(low+high)/2; //折半
if(L.r[0].key<L.r[m].key) high=m-1; //插入点在前一子表
else low=m+1; //插入点在后一子表
}//while
for(j=i-1;j>=high+1;--j) L.r[j+1]=L.r[j]; //记录后移
L.r[high+1]=L.r[0]; //将r[0]即原r[i],插入到正确位置
} //for
} //BInsertSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
BInsertSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,82 @@
//算法8.3 希尔排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
void ShellInsert(SqList &L,int dk)
{
//对顺序表L做一趟增量是dk的希尔插入排序
int i,j;
for(i=dk+1;i<=L.length;++i)
if(L.r[i].key<L.r[i-dk].key)
{ //需将L.r[i]插入有序增量子表
L.r[0]=L.r[i]; //暂存在L.r[0]
for(j=i-dk;j>0&& L.r[0].key<L.r[j].key;j-=dk)
L.r[j+dk]=L.r[j]; //记录后移,直到找到插入位置
L.r[j+dk]=L.r[0]; //将r[0]即原r[i],插入到正确位置
} //for
}
//ShellInsert
void ShellSort(SqList &L,int dt[ ],int t){
//按增量序列dt[0..t-1]对顺序表L作t趟希尔排序
int k;
for(k=0;k<t;++k)
ShellInsert(L,dt[k]); //一趟增量为dt[t]的希尔插入排序
} //ShellSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
int i,t;//增量数组的长度
int *dt=new int[MAXSIZE];//增量数组
cout<<"请输入增量个数:\n";
cin>>t;
for(i=0;i<t;i++)
{
cout<<"第"<<i+1<<"个增量:\n";
cin>>dt[i];
}
ShellSort(L,dt,t);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,70 @@
//算法8.4 冒泡排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
void BubbleSort(SqList &L)
{
//对顺序表L做冒泡排序
int m,j,flag;
ElemType t;
m=L.length-1; flag=1; //flag用来标记某一趟排序是否发生交换
while((m>0)&&(flag==1))
{
flag=0; //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
for(j=1;j<=m;j++)
if(L.r[j].key>L.r[j+1].key)
{
flag=1; //flag置为1,表示本趟排序发生了交换
t=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=t; //交换前后两个记录
} //if
--m;
} //while
} //BubbleSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
BubbleSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,89 @@
//算法8.5 快速排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
int Partition(SqList &L,int low,int high)
{
//对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置
int pivotkey;
L.r[0]=L.r[low]; //用子表的第一个记录做枢轴记录
pivotkey=L.r[low].key; //枢轴记录关键字保存在pivotkey中
while(low<high)
{ //从表的两端交替地向中间扫描
while(low<high&&L.r[high].key>=pivotkey) --high;
L.r[low]=L.r[high]; //将比枢轴记录小的记录移到低端
while(low<high&&L.r[low].key<=pivotkey) ++low;
L.r[high]=L.r[low]; //将比枢轴记录大的记录移到高端
}//while
L.r[low]=L.r[0]; //枢轴记录到位
return low; //返回枢轴位置
}//Partition
void QSort(SqList &L,int low,int high)
{ //调用前置初值:low=1; high=L.length;
//对顺序表L中的子序列L.r[low..high]做快速排序
int pivotloc;
if(low<high)
{ //长度大于1
pivotloc=Partition(L,low,high); //将L.r[low..high]一分为二,pivotloc是枢轴位置
QSort(L,low,pivotloc-1); //对左子表递归排序
QSort(L,pivotloc+1,high); //对右子表递归排序
}
} //QSort
void QuickSort(SqList &L)
{
//对顺序表L做快速排序
QSort(L,1,L.length);
} //QuickSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
QuickSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,65 @@
//算法8.6 简单选择排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
void SelectSort(SqList &L)
{
//对顺序表L做简单选择排序
int i,j,k;
ElemType t;
for(i=1;i<L.length;++i)
{ //在L.r[i..L.length] 中选择关键字最小的记录
k=i;
for(j=i+1;j<=L.length;++j)
if(L.r[j].key<L.r[k].key) k=j; //k指向此趟排序中关键字最小的记录
if(k!=i) {t=L.r[i];L.r[i]=L.r[k];L.r[k]=t;} //交换r[i]与r[k]
} //for
} // SelectSort
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
SelectSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,64 @@
//算法8.7 筛选法调整堆
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
void HeapAdjust(SqList &L,int s,int m)
{
//假设r[s+1..m]已经是堆,将r[s..m]调整为以r[s]为根的大根堆
ElemType rc;
int j;
rc=L.r[s];
for(j=2*s;j<=m;j*=2)
{ //沿key较大的孩子结点向下筛选
if(j<m&&L.r[j].key<L.r[j+1].key) ++j; //j为key较大的记录的下标
if(rc.key>=L.r[j].key) break; //rc应插入在位置s上
L.r[s]=L.r[j]; s=j;
}
L.r[s]=rc; //插入
} //HeapAdjust
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待调整的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
HeapAdjust(L,1,L.length);
cout<<"调整后的结果为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,75 @@
//算法8.8 建初堆
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
//用算法8.7 筛选法调整堆
void HeapAdjust(SqList &L,int s,int m)
{
//假设r[s+1..m]已经是堆,将r[s..m]调整为以r[s]为根的大根堆
ElemType rc;
int j;
rc=L.r[s];
for(j=2*s;j<=m;j*=2)
{ //沿key较大的孩子结点向下筛选
if(j<m&&L.r[j].key<L.r[j+1].key) ++j; //j为key较大的记录的下标
if(rc.key>=L.r[j].key) break; //rc应插入在位置s上
L.r[s]=L.r[j]; s=j;
}
L.r[s]=rc; //插入
} //HeapAdjust
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
void CreatHeap(SqList &L)
{
//把无序序列L.r[1..n]建成大根堆
int i,n;
n=L.length;
for(i=n/2;i>0;--i) //反复调用HeapAdjust
HeapAdjust(L,i,n);
} //CreatHeap
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
CreatHeap(L);
cout<<"建立成堆的序列为:"<<endl;
show(L);
}

View File

@@ -0,0 +1,90 @@
//算法8.9 堆排序
#include <iostream>
using namespace std;
#define MAXSIZE 20 //顺序表的最大长度
typedef struct
{
int key;
char *otherinfo;
}ElemType;
//顺序表的存储结构
typedef struct
{
ElemType *r; //存储空间的基地址
int length; //顺序表长度
}SqList; //顺序表类型
//用算法8.7 筛选法调整堆
void HeapAdjust(SqList &L,int s,int m)
{
//假设r[s+1..m]已经是堆,将r[s..m]调整为以r[s]为根的大根堆
ElemType rc;
int j;
rc=L.r[s];
for(j=2*s;j<=m;j*=2)
{ //沿key较大的孩子结点向下筛选
if(j<m&&L.r[j].key<L.r[j+1].key) ++j; //j为key较大的记录的下标
if(rc.key>=L.r[j].key) break; //rc应插入在位置s上
L.r[s]=L.r[j]; s=j;
}
L.r[s]=rc; //插入
}
//HeapAdjust
void Create_Sq(SqList &L)
{
int i,n;
cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
cin>>n; //输入个数
cout<<"请输入待排序的数据:\n";
while(n>MAXSIZE)
{
cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
cin>>n;
}
for(i=1;i<=n;i++)
{
cin>>L.r[i].key;
L.length++;
}
}
//用算法8.8 建初堆
void CreatHeap(SqList &L)
{
//把无序序列L.r[1..n]建成大根堆
int i,n;
n=L.length;
for(i=n/2;i>0;--i) //反复调用HeapAdjust
HeapAdjust(L,i,n);
} //CreatHeap
void HeapSort(SqList &L)
{
//对顺序表L进行堆排序
int i;
ElemType x;
CreatHeap(L); //把无序序列L.r[1..L.length]建成大根堆
for(i=L.length;i>1;--i)
{
x=L.r[1]; //将堆顶记录和当前未经排序子序列L.r[1..i]中最后一个记录互换
L.r[1]=L.r[i];
L.r[i]=x;
HeapAdjust(L,1,i-1); //将L.r[1..i-1]重新调整为大根堆
}//for
}//HeapSort
void show(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
cout<<L.r[i].key<<endl;
}
void main()
{
SqList L;
L.r=new ElemType[MAXSIZE+1];
L.length=0;
Create_Sq(L);
HeapSort(L);
cout<<"排序后的结果为:"<<endl;
show(L);
}