1.顺序表是线性表的( )
B.顺序存储结构
2.线性表L=(a1,a2,…,an),下列说法正确的是( )
D.
除第一个和最后一个元素外,其他元素都有且仅有一个直接前驱和一个直接后继
3对于顺序表的优缺点,以下说法错误的是( )。
C.插入和删除运算较方便
在n个数据元素的顺序表中,算法时间复杂度为O(1)的操作是( )
(1) 访问第i个结点(1≤i≤n)
(2) 求第i个结点的直接前驱(2≤i≤n)
(3) 求第i个结点的直接后继(1≤i≤n-1)
(4) 在第i个结点后插入一个新结点(1≤i≤n)
(5) 删除第i个结点(1≤i≤n)
(6) 排序
B.
(1)(2)(3)
等概率情况下,在表长为n的顺序表中插入一个元素所需移动的元素平均个数为( )
B.
n/2
2-6
在一个长度为n的顺序表中,删除第i个元素(1≤i≤n)时需要移动( )个元素。
A.
n-i
在一个长度为n的顺序表中,向第i个元素(1≤i≤n+1)位置插入一个新元素时需要从后向前移动多少个元素。
B.
n-i+1
(neuDS)一个顺序表所占用的存储空间大小与( )无关。
C.
元素的存放顺序
顺序存储表示中数据元素之间的逻辑关系是由( )表示的。
C.
存储位置
2-10
若长度为n的非空线性表采用顺序存储结构,在表的第i个位置插入一个数据元素的合法值应该是( )。
B.
1≤i≤n+1
2-11
顺序表中第1个元素的存储地址是2000,每个元素的长度为4,则第5个元素的地址是( )
B.
2016
链表 - 存储结构
链表要求内存中可用存储单元的地址 ▁▁▁▁▁ 。
D.连续或不连续都可以
链表不具有的特点是____。
A.可随机访问任一元素
线性表L在什么情况下适用于使用链式结构实现?
- 需不断对L进行删除插入
单链表又称为线性链表,在单链表上实施插入和删除操作( )。
B.不需移动结点,只需改变结点指针
2-5
对于一个具有N个结点的单链表,在给定值为x的结点后插入一个新结点的时间复杂度为
C.O(N)
在具有N个结点的单链表中,实现下列哪个操作,其算法的时间复杂度是O(N)?
C.
遍历链表和求链表的第i个结点
创建一个包括n个结点的单链表的时间复杂度是( )
B.O(n)
静态链表中指针表示的是。
B.数组下标
在单链表中,若p所指的结点不是最后结点,在p之后插入s所指结点,则执行
C.
s->next=p->next; p->next=s;
带头结点的单链表h为空的判定条件是:
B.
h->next == NULL;
已知头指针 h 指向一个带头结点的非空单循环链表,结点结构为 data | next,其中 next 是指向直接后继结点的指针,p 是尾指针,q 是临时指针。现要删除该链表的第一个元素,正确的语句序列是:
D.
q=h->next; h->next=q->next; if (p==q) p=h; free(q);
在双向链表存储结构中,删除p所指的结点,相应语句为:
C.
p->prior->next=p->next; p->next->prior=p->prior;
已知表头元素为c的单链表在内存中的存储状态如下表所示:
现将f存放于1014H处,并插入到单链表中,若f在逻辑上位于a和e之间,则a、e、f的“链接地址”依次
是:
D.
1014H, 1004H, 1010H
双链表 - 插入结点
在双链表中,将 s 所指新结点插入到 p 所指结点之后,其语句应该为 ▁▁▁▁▁ 。
C.
s->next = p->next; p->next->prev = s; p->next = s; s->prev = p;
在双链表中,删除 p 所指结点的后继结点,其语句应该为 ▁▁▁▁▁ 。
C.
s = p->next; s->next->prev = p; p->next = s->next;
和顺序栈相比,链栈有一个比较明显的优势是()。
A.
通常不会出现栈满的情况
栈在( )中有所应用
D.
前三个选项都有
对空栈 S 进行 Push 和 Pop 操作,入栈序列为 a, b, c, d, e,经过 Push, Push, Pop, Push, Pop, Push, Push, Pop 操作后,得到的出栈序列是:
D.b, c, e
在作进栈运算时,应先判别栈是否(① );在作退栈运算时应先判别栈是否(② )。当栈中元素为n个,作进栈运算时发生上溢,则说明该栈的最大容量为(③ )。
①: A. 空 B. 满 C. 上溢 D. 下溢
②: A. 空 B. 满 C. 上溢 D. 下溢
③: A. n-1 B. n C. n+1 D. n/2
我写错了
向一个栈顶指针为h的带头结点的链栈中插入指针s所指的结点时,应执行( )操作。
D.
s->next=h->next ;h->next=s ;
用带头结点的单链表表示链式栈,其头指针为head,结点的指针域为next,则出栈操作的语句为( )
A.
head->next=head->next->next;
用S表示入栈操作,X表示出栈操作,若元素入栈的顺序为1234,为了得到1342出栈顺序,相应的S和X的操作串为( )。
D.
SXSSXSXX
设一个堆栈的入栈顺序是1、2、3、4、5。若第一个出栈的元素是4,则最后一个出栈的元素必定是:
D.
1或者5
设有一顺序栈S,元素s1,s2,s3,s4,s5,s6依次进栈,如果6个元素出栈的顺序是s2,s3,s4, s6 , s5,s1,则栈的容量至少应该是( )。
B.3
若一个栈用数组data[1..n]存储,初始栈顶指针top为n,则以下元素x进栈的正确操作是( )。
D.
data[top]=x; top--;
利用栈实现十进制整数1234转八进制,以下哪项栈表状态符合实际情况:
B.B
2-12
表达式求值 。
表达式3 * 2 ^ (4 + 2 * 2 - 6 * 3) - 5求值过程中当扫描到 6 时,运算数栈和运算符栈分别为( ),其中 ^ 为乘幂 。
C.
3, 2, 8; * ^ ( -
现有队列 Q 与栈 S,初始时 Q 中的元素依次是{ 1, 2, 3, 4, 5, 6 }(1在队头),S 为空。若允许下列3种操作:(1)出队并输出出队元素;(2)出队并将出队元素入栈;(3)出栈并输出出栈元素,则不能得到的输出序列是:
C.
3, 4, 5, 6, 1, 2
循环队列的引入,目的是为了克服( )。
A.
假溢出问题
栈和队列的共同点是( )。
C.
只允许在端点处插入和删除元素
2、下列与队列结构有关联的是
D.
先到先服务的作业调度
(neuDS)在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判空条件是( )。
A.
front==rear
(neuDS)在循环顺序队列中,假设以少用一个存储单元的方法来区分队列判满和判空的条件,front和rear分别为队首和队尾指针,它们分别指向队首元素和队尾元素的下一个存储单元,队列的最大存储容量为maxSize,则队列的判满条件是( )。
D.
front==(rear+1)% maxSize
若用大小为6的数组来实现循环队列,且当前front和rear的值分别为0和4。当从队列中删除三个元素,再加入三个元素后,front和rear的值分别为多少?
B.
3和1
现采用大小为10的数组实现一个循环队列。设在某一时刻,队列为空且此时front和rear值均为5。经过若干操作后,front为8,rear为2,问:此时队列中有多少个元素?
没写
以下关于二叉树的说法中正确的是( )
C.
二叉树中每个节点的度可以小于2
对于图所示二叉树,试给出:
它的顺序存储结构
A.
ABCDEF^^^G^^H
一棵满二叉树中127个节点,其中叶子节点的个数是( )
B.
64
以下说法错误的是( )
C.
树的度就是树的深度
2-5
以下二叉树的先序遍历序列是( )。
B.
ABCDEGFH
以下二叉树的中序遍历序列是( )。
B.
CDBEAFGH
以下二叉树的后序遍历序列是( )。
A.
DCEBFHGA
若一棵二叉树的后序遍历序列是{ 1, 3, 2, 6, 5, 7, 4 },中序遍历序列是{ 1, 2, 3, 4, 5, 6, 7 },则下列哪句是错的?
A.
这是一棵完全二叉树
已知二叉树的前序遍历序列为 ABDCEFG,中序遍历序列为 DBCAFEG,则后序遍历序列为 __
B.
DCBFGEA
已知二叉树的先序遍历序列为ABCDEFGH,中序遍历序列为CBEDFAGH,则该二叉树形态中,父节点的右子节点为()。
C.
G
若根节点为高度1,一棵具有 1025 个结点的二叉树的高度为 ▁▁▁▁▁ 。
C.
11~1025 之间
若一棵二叉树具有10个度为2的结点,5个度为1的结点,则度为0的结点个数是( )
B.
11
设 T 是非空二叉树,若 T 的先序遍历和中序遍历序列相同,则 T 的形态是 __
D.
所有结点只有右孩子
设 T 是非空二叉树,若 T 的先序遍历和后序遍历序列相同,则 T 的形态是 __
A.
只有一个根结点
设 T 是非空二叉树,若 T 的后序遍历和中序遍历序列相同,则 T 的形态是 __
C.
所有结点只有左孩子
一棵二叉树中有7个度为2的结点和5个度为1的结点,其总共有( )个结点。
C.20
在任何一棵二叉树中,若结点a有左孩子b、右孩子c,则在结点的先序序列、中序序列、后序序列中,( )。
A.
结点b一定在结点a的前面
C.
结点b一定在结点c的前面
D.
结点a一定在结点b的前面
答案错误:0 分
2-18
分数 2
作者 YJ
单位 西南石油大学
在二叉树结点的先序序列,中序序列和后序序列中,所有叶子结点的先后顺序( )。
B.
完全相同
一棵二叉树中,双分支结点数为15,单分支结点数为30,则叶子结点数为()个。
B.
16
某森林 F 对应的二叉树为 T,若 T 的先序遍历序列是 a, b, d, c, e, g, f,中序遍历序列是 b, d, a, e, g, c, f,则 F 中的树的棵树是:
A.
1
B.
2
C.
3
答案错误:0 分
创建提问
2-21
用孩子链存储结构表示树,其优点之一是____比较方便。
A.
判断两个指定结点是不是兄弟
C.
判断指定结点在第几层
D.
计算指定结点的度数
答案错误:0 分
2-22
用双亲存储结构表示树,其优点之一是比较方便____。
A.
找指定结点的双亲结点
对 n 个互不相同的符号进行哈夫曼编码。若生成的哈夫曼树共有 115 个结点,则 n 的值是:
C.
58
答案正确:3 分
已知字符集{ a, b, c, d, e, f, g, h }。若各字符的哈夫曼编码依次是 0100, 10, 0000, 0101, 001, 011, 11, 0001,则编码序列 0100011001001011110101 的译码结果是:
D.
afeefgd
设无向图为 G=(V,E),其中 V={v1,v2,v3,v4},E={(v1,v2),(v3,v4),(v4,v1),(v2,v3),(v1,v3)}。则每个顶点的度依次为:
C.
3, 2, 3, 2
对于给定的有向图如下,其邻接表为:
C.
对于给定的有向图如下,其邻接矩阵为:
D.
以下哪个是给定无向带权图的邻接矩阵?
B.
给出如下图所示的具有 7 个结点的网 G,哪个选项对应其正确的邻接矩阵?
B.
给定一个图的邻接矩阵如下,则下列哪个是对应的图?
D.
答案正确:3 分
2-7
分数 3
作者 魏宝刚
单位 浙江大学
已知一个无向图的顶点集为 {V0,V1,⋯,V7},其邻接矩阵如下所示:
以下哪项不可能是从 V0 出发的广度优先遍历序?
B.
V0,V3,V1,V4,V2,V6,V5,V7
已知一个无向图的顶点集为 {V0,V1,⋯,V7},其邻接矩阵如下所示:
以下哪项不可能是从 V0 出发的深度优先遍历序?
D.
V0,V1,V4,V3,V6,V7,V2,V5
对下图从顶点C出发进行广度优先搜索,哪个是正确的搜索序列?
D.
CBDAEHFG
对下图从顶点C出发进行深度优先搜索,哪个是错误的搜索序列?
B.
CDABEHFG
以下哪个不是给定无向带权图的最小生成树?
D.
给出如下图所示的具有 7 个结点的网 G,采用Prim算法,从4号结点开始,给出该网的最小生成树。下列哪个选项给出了正确的树结点收集顺序?
D.
4563201
给定有向图如下。下列哪个选项不是对应的拓扑序列?
D.
abdfce
下列关于AOE网的叙述中,不正确的是( )。
B.
任何一个关键活动提前完成,那么整个工程将会提前完成
用邻接表存储图所用的空间大小( )
A.
与图的顶点和边数有关
下图是一个有 10 个活动的 AOE 网,时间余量最大的活动是:
B.
g
顺序表的基本操作(动态分配)
分数 70
全屏浏览题目
切换布局
作者 魏峻
单位 陕西理工大学
掌握顺序表的基本操作,插入、删除、查找等运算。参照main函数,补全各操作函数。
线性表的顺序存储定义:是指用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中。
采用顺序存储结构的线性表通常称为顺序表。
答案:
#include<stdio.h>
#include<malloc.h>
#define LIST_INIT_SIZE 10//初始分配量
#define LISTINCREMENT 2//分配增量
typedef int ElemType;//重定义元素类型
typedef struct {
ElemType* elem;//存储空间的基地址
int length;//当前的长度
int listsize;//当前分配的存储容量
}SqList;
void InitList_Sq(SqList* L) {//构造一个空的线性表
L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
L->length = 0;
L->listsize = LIST_INIT_SIZE;
}
void CreatList_Sq(SqList* L) {
int i = 0;
int el = 0;
int* arr = (int*)malloc(sizeof(int) * LIST_INIT_SIZE);
do {
scanf("%d", &el);
arr[i] = el;
i++;
} while (el != -1);
int j = 0;
int count = i - 1;
for (j = 0; j < count; j++) {
L->elem[j] = arr[i - 2];
i--;
}
L->length = count;
}
void InsertList_Sq(SqList* L, int index, ElemType e) {//头位置插入
if (L->length == L->listsize) {//判断元素是否已满
int newSize = L->listsize + LISTINCREMENT;
ElemType* newelem = (ElemType*)realloc(L->elem, newSize * sizeof(ElemType));
L->elem = newelem;
L->listsize = newSize;
}
int i = 0;
for (i = L->length; i > index - 1; --i) {
L->elem[i] = L->elem[i - 1];
}
L->elem[i] = e;
L->length++;
}
void DeleteList_Sq(SqList* L, int index, ElemType* e) {//删除
*e = L->elem[index - 1];
for (int i = index; i < L->length; i++) {
L->elem[i - 1] = L->elem[i];
}
L->length--;
}
void PrintList_Sq(SqList* L) {
if (L->length == 0) {
printf("顺序表为空!\n");
return;
}
printf("顺序表里的元素有:\n");
for (int i = 0; i < L->length; i++) {
printf("%3d", L->elem[i]);
}
printf("\n");
}
void ClearList_Sq(SqList* L) {
printf("正在清空顺序表...\n");
L->length = 0;
}
int main() {
SqList L;
InitList_Sq(&L);
CreatList_Sq(&L);
ElemType e;
scanf("%d", &e);
PrintList_Sq(&L);
printf("顺序表的长度是:%d\n", L.length);
InsertList_Sq(&L, 1, e);
printf("在顺序表头位置插入元素%d...\n", e);
PrintList_Sq(&L);
DeleteList_Sq(&L, L.length, &e);
printf("在顺序表尾位置删除元素%d...\n", e);
PrintList_Sq(&L);
ClearList_Sq(&L);
PrintList_Sq(&L);
return 0;
}
掌握单链表的基本操作,插入、删除、查找等运算。参照main函数,补全各操作函数。
单链表包括两个域:
- 数据域:用来存储结点的数据值
- 指针域:用来存储数据元素的直接后继的地址(或位置)
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void InitList_L(LinkList &PHead);
void InsertList_L(LinkList &L, int i, ElemType e);
void DeleteList_L(LinkList &L, int i, ElemType &e);
void CreatListFromHead_L(LinkList &PHead);
void CreatListFromTail_L(LinkList &PHead);
void PrintList_L(LinkList &L); //已知
bool IsEmptyList_L(LinkList &L); //已知
void GetElemList_L(LinkList &L, int i, ElemType &e);
int LocateElemList_L(LinkList &L, ElemType e); //已知
int LengthList_L(LinkList &L); //已知
void FreeList_L(LinkList &L); //已知
int main()
{
LinkList L1, L2;
ElemType e, data;
int index, n;
InitList_L(L1);
InitList_L(L2);
CreatListFromHead_L(L1);
CreatListFromTail_L(L2);
scanf("%d %d %d %d", &e, &index, &data, &n);
printf("头插法创建单链表L1...\n");
PrintList_L(L1);
printf("单链表L1的长度为:%d\n", LengthList_L(L1));
printf("尾插法创建单链表L2...\n");
PrintList_L(L2);
printf("单链表L2的长度为:%d\n", LengthList_L(L2));
printf("在单链表L1中第%d个位置插入元素%d...\n", index, e);
InsertList_L(L1, index, e);
PrintList_L(L1);
printf("删除单链表L2中第%d个位置的元素...\n", n);
DeleteList_L(L2, n, e);
PrintList_L(L2);
printf("删除的元素是:%d\n", e);
printf("在单链表L1中查找元素...\n");
GetElemList_L(L1, index, e);
printf("单链表L1中第%d个元素的值为:%d\n", index, e);
printf("在单链表L2中查找元素的位置...\n");
printf("单链表L2中元素%d的位置为:%d", data, LocateElemList_L(L2, data));
return 0;
}
void PrintList_L(LinkList &L)
{
LinkList p = L->next;
//printf("单链表:");
while(p)
{
printf("%3d", p->data);
p = p->next;
}
printf("\n");
return;
}
bool IsEmptyList_L(LinkList &L)
{
return L->next == NULL;
}
int LocateElemList_L(LinkList &L, ElemType e)
{
LinkList p = L->next;
int j = 1;
while(p && p->data != e)
{
p = p->next;
j++;
}
if(p) return j;
else return -1;
}
int LengthList_L(LinkList &L)
{
LinkList p = L;
int len = 0;
while(p->next != NULL)
{
len++;
p = p->next;
}
return len;
}
void FreeList_L(LinkList &L)
{
LinkList p = L, q;
while(p->next != NULL)
{
q = p;
p = p->next;
free(q);
}
free(p);
return;
}
void InitList_L(LinkList &PHead)
{
PHead = (LinkList)malloc(sizeof(LNode));
if(!PHead) return;
PHead->next = NULL;
}
void InsertList_L(LinkList &L, int i, ElemType e)
{
LinkList p;
p = L;
int j=1;
while( p && j<i ) //p指向第i-1个位置
{
p = p->next;
j++;
}
if(!p||j>i)
{
printf("插入的位置不合法!\n");
return;
}
LinkList s=(LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
}
void DeleteList_L(LinkList &L, int i, ElemType &e)
{
LinkList p,q;
p = L;
int j=1;
while( p->next && j<i )
{
p = p->next;
j++;
}
if(!(p->next)||j>i)
{
printf("删除元素的位置不合法!\n");
e=-1;
return;
}
e = p->next->data;
q = p->next;
p->next = q->next;
free(q);
}
void CreatListFromHead_L(LinkList &PHead)
{
ElemType e;
scanf("%d",&e);
while(e!=-1)
{
LinkList s=(LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = NULL;
s->next = PHead->next;
PHead->next = s;
scanf("%d",&e);
}
}
void CreatListFromTail_L(LinkList &PHead)
{
LinkList p;
ElemType e;
p = PHead;
scanf("%d",&e);
while(e!=-1)
{
LinkList s=(LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = NULL;
p->next = s;
p = s;
scanf("%d",&e);
}
}
void GetElemList_L(LinkList &L, int i, ElemType &e)
{
LinkList p;
p = L;
int j=1;
while(p&&j<i)
{
p = p->next;
j++;
}
if(!p||j>i)
{
printf("第%d个元素不存在!\n",i);
e=-1;
return;
}
e = p->next->data;
}
掌握顺序栈的基本操作,初始化、入栈、出栈,以及取栈顶元素等运算。参照main函数,补全各操作函数。
栈:限定仅在表尾进行插入或删除操作的线性表。表尾端称为栈顶 (Top),表头段称为栈底 (Bottom)。特点:后进先出(LIFO)
#include <stdio.h>
#include <malloc.h>
#define STACK_INIT_SIZE 10
#define STACKINCREMENT 2
typedef int SElemType;
typedef struct
{
SElemType *base; // 栈底指针
SElemType *top; // 栈顶指针
int stacksize; // 当前分配的空间
}SqStack;
void InitStack(SqStack &S); // 构造一个空栈
void PushStack(SqStack &S, SElemType e); // 将e入栈
void PopStack(SqStack &S, SElemType &e); // 出栈,删除栈顶元素并返回给e
void CreatStack(SqStack &S); // 通过连续输入构造一个栈(已知)
void PrintStack(SqStack &S); // 输出栈里的元素(已知)
int LengthStack(SqStack &S); // 栈里元素的个数
void GetTopStack(SqStack &S, SElemType &e); // 获取栈顶元素
void ClearStack(SqStack &S); // 清空栈即将栈置为空栈
int main()
{
SqStack S;
SElemType e;
InitStack(S);
CreatStack(S);
scanf("%d", &e);
PrintStack(S);
printf("顺序栈S中元素的个数:%d\n", LengthStack(S));
printf("元素%d正在入栈...\n", e);
PushStack(S, e);
PrintStack(S);
printf("出栈操作...\n");
PopStack(S, e);
printf("出栈的元素是:%d\n", e);
printf("出栈操作...\n");
PopStack(S, e);
printf("出栈的元素是:%d\n", e);
PrintStack(S);
GetTopStack(S, e);
printf("栈顶的元素是:%d\n", e);
PrintStack(S);
printf("正在清空栈...\n");
ClearStack(S);
PrintStack(S);
return 0;
}
void InitStack(SqStack &S){
S.base = (SElemType * )malloc(STACK_INIT_SIZE * sizeof(SElemType));
if(!S.base) return;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return;
} // 构造一个空栈
void PushStack(SqStack &S, SElemType e){
if(S.top - S.base >= S.stacksize){
S.base = (SElemType * )realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
if(!S.base)return;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
//*S.top++ = e;
*S.top = e;
S.top++;
return;
} // 将e入栈
void PopStack(SqStack &S, SElemType &e){
if(S.base == S.top){
printf("栈为空!\n");
e = -1;
return;
}
//e = * --S.top;
S.top--;
e = *S.top;
return;
} // 出栈,删除栈顶元素并返回给e
void CreatStack(SqStack &S)
{
SElemType e;
scanf("%d", &e);
while(e != -1)
{
PushStack(S, e);
scanf("%d", &e);
}
return;
}
void PrintStack(SqStack &S)
{
if(S.base == S.top)
{
printf("栈为空!\n");
return;
}
printf("顺序栈里的元素有:");
for(SElemType *p=S.top-1; p>=S.base; p--)
printf("%3d", *p);
printf("\n");
return;
}
int LengthStack(SqStack &S){
return S.top - S.base;
} // 栈里元素的个数
void GetTopStack(SqStack &S, SElemType &e){
if(S.top == S.base){
printf("栈为空!\n");
e = -1;
return;
}
e = * (S.top-1);
return;
} // 获取栈顶元素
void ClearStack(SqStack &S){
S.top = S.base;
return;
} // 清空栈即将栈置为空栈
掌握二叉树的基本操作。参照main函数,补全各操作函数。
线性结构:第一个数据元素(无前驱);最后一个数据元素(无后继);其它数据元素(一个前驱,一个后继)。
树型结构:根结点(无前驱);多个叶子结点(无后继);其它数据元素(一个前驱,多个后继)。
#include <stdio.h>
#include <malloc.h>
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
void CreatBiTree(BiTree &T); // 先序次序构造二叉树
void Visit(TElemType ch); // 访问节点元素
void PreOrderTraverse(BiTree &T); // 先序遍历二叉树
void InOrderTraverse(BiTree &T); // 中序遍历二叉树
void PostOrderTraverse(BiTree &T); // 后序遍历二叉树
BiTNode *SearchNode(BiTree &T, TElemType e); //查找元素e的节点位置
int BiTreeHigh(BiTree &T); //计算二叉树的深度
int CountLeaf(BiTree &T); // 统计二叉树叶子节点的个数
int CountNodes(BiTree &T); // 统计二叉树的节点个数
int main()
{
TElemType ch = getchar(); getchar();
BiTree T;
CreatBiTree(T);
printf("先序遍历二叉树:");
PreOrderTraverse(T);printf("\n");
printf("中序遍历二叉树:");
InOrderTraverse(T);printf("\n");
printf("后序遍历二叉树:");
PostOrderTraverse(T);printf("\n");
if(SearchNode(T, ch))
printf("二叉树中有节点元素%c!\n", ch);
else
printf("二叉树中没有节点元素%c!\n", ch);
printf("二叉树叶子节点总数为:%d\n", CountLeaf(T));
printf("二叉树节点总数为:%d\n", CountNodes(T));
printf("二叉树深度为:%d\n", BiTreeHigh(T));
return 0;
}
void CreatBiTree(BiTree &T){
char ch = getchar();
if(ch == '#')
T = NULL;
else{
T = (BiTNode *)malloc(sizeof(BiTNode));
if(!T) return;
T->data = ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
return;
} // 先序次序构造二叉树
void Visit(TElemType ch) // 访问节点元素
{
printf("%c", ch);
return;
}
void PreOrderTraverse(BiTree &T){
if(T){
Visit(T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
return;
} // 先序遍历二叉树
void InOrderTraverse(BiTree &T){
if(T){
InOrderTraverse(T->lchild);
Visit(T->data);
InOrderTraverse(T->rchild);
}
return;
} // 中序遍历二叉树
void PostOrderTraverse(BiTree &T){
if(T){
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
Visit(T->data);
}
return;
} // 后序遍历二叉树
BiTNode *SearchNode(BiTree &T, TElemType e){
if(!T) return NULL;
if(T->data == e) return T;
else{
BiTNode *p = SearchNode(T->lchild,e);
if(!p) p = SearchNode(T->rchild,e);
return p;
}
} //查找元素e的节点位置
int BiTreeHigh(BiTree &T){
int h, lh, rh;
if(T == NULL) return 0;
else{
lh = BiTreeHigh(T->lchild);
rh = BiTreeHigh(T->rchild);
h = (lh > rh?lh:rh) + 1;
}
return h;
} //计算二叉树的深度
int CountLeaf(BiTree &T){
if(T == NULL) return 0;
else if(T->lchild == NULL && T->rchild == NULL) return 1;
else return CountLeaf(T->lchild) + CountLeaf(T->rchild);
} // 统计二叉树叶子节点的个数
int CountNodes(BiTree &T){
if(T){
if(T->lchild == NULL && T->rchild == NULL) return 1;
else return CountNodes(T->lchild) +CountNodes(T->rchild) + 1;
}
return 0;
} // 统计二叉树的节点个数
掌握二叉树的基本操作(非递归方法)。参照main函数,补全各操作函数。
递归的底层实现依靠的是栈存储结构,因此,二叉树的遍历既可以直接采用递归思想实现,
#include <stdio.h>
#include <malloc.h>
typedef char TElemType;
typedef struct BiTNode // 定义二叉树
{
TElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
void CreatBiTree(BiTree &T); // 先序递归构造二叉树
void Visit(TElemType ch); // 访问节点元素
void PreOrderTraverse(BiTree &T); // 先序遍历二叉树
void InOrderTraverse(BiTree &T); // 中序遍历二叉树
void PostOrderTraverse(BiTree &T); // 后序遍历二叉树
void LevelOrderTraverse(BiTree &T); // 层次遍历二叉树
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct StackNode // 定义链栈
{
BiTree *top;
BiTree *base;
int stacksize;
}Stack;
void InitStack(Stack &S); // 初始化栈
void PushStack(Stack &S, BiTree &BiTNode); // 入栈
BiTree PopStack(Stack &S); // 出栈
BiTree GetTopStack(Stack &S); // 取栈顶元素
typedef struct QNode // 定义链队
{
BiTree pBiTNode;
struct QNode *next;
}QNode, *QNodeLink;
typedef struct
{
QNodeLink frot;
QNodeLink rear;
}LinkQueue;
void InitLinkQueue(LinkQueue &Q); // 构造一个空队列
void EnQueue(LinkQueue &Q, BiTree T); // 入队操作
BiTree DeQueue(LinkQueue &Q); // 出队操作
int main()
{
BiTree T;
CreatBiTree(T);
//Visit(T->data);
//printf("\n");
//Stack S;
//InitStack(S);
//PushStack(S, T);
//BiTree p;
//p = GetTopStack(S);
//Visit(p->data);
//int cha = S.top-S.base;
//printf("%d",(int)(S.top - S.base));
printf("先序非递归遍历二叉树:");
PreOrderTraverse(T);
printf("中序非递归遍历二叉树:");
InOrderTraverse(T);
printf("后序非递归遍历二叉树:");
PostOrderTraverse(T);
printf("层次遍历二叉树(从上到下,每层从左到右):");
LevelOrderTraverse(T);
return 0;
}
void CreatBiTree(BiTree &T){
char ch = getchar();
if(ch == '#')
T = NULL;
else{
T = (BiTNode *)malloc(sizeof(BiTNode));
if(!T) return;
T->data = ch;
CreatBiTree(T->lchild);
CreatBiTree(T->rchild);
}
return;
} // 先序递归构造二叉树
void Visit(TElemType ch) // 访问节点元素
{
printf("%c", ch);
return;
}
void PreOrderTraverse(BiTree &T){
Stack S;
InitStack(S);
BiTree p;
PushStack(S, T);
while(S.base != S.top){
p = GetTopStack(S);
//int i=0;
while(p != NULL){
Visit(p->data);
PushStack(S, p->lchild);
p = GetTopStack(S);
//printf("数字%d\n",i);
//i++;
}
PopStack(S);
if(S.base != S.top){
p = PopStack(S);
PushStack(S, p->rchild);
}
}
printf("\n");
return;
} // 先序遍历二叉树
void InOrderTraverse(BiTree &T){
Stack S;
InitStack(S);
BiTree p;
PushStack(S, T);
while(S.base != S.top){
p = GetTopStack(S);
while(p != NULL){
PushStack(S, p->lchild);
p = GetTopStack(S);
}
PopStack(S);
if(S.base != S.top){
p = PopStack(S);
Visit(p->data);
PushStack(S, p->rchild);
}
}
printf("\n");
return;
} // 中序遍历二叉树
void PostOrderTraverse(BiTree &T){
Stack S;
InitStack(S);
BiTree p = T, q;
do{
while(p){
PushStack(S, p);
p = p->lchild;
}
q = NULL;
while(S.base != S.top){
p = GetTopStack(S);
if(p->rchild == NULL || q == p->rchild){
Visit(p->data);
q = p;
PopStack(S);
}
else{
p = p->rchild;
break;
}
}
}while(S.base != S.top);
printf("\n");
return;
} // 后序遍历二叉树
void LevelOrderTraverse(BiTree &T){
LinkQueue Q;
BiTree p;
InitLinkQueue(Q);
if(T){
EnQueue(Q, T);
//int i=0;
while(Q.rear != Q.frot){
p = DeQueue(Q);
Visit(p->data);
//printf("\n数字出现第一次的%d",i);
if(p->lchild) EnQueue(Q, p->lchild);
if(p->rchild) EnQueue(Q, p->rchild);
//printf("\n数字出现第二次的%d",i);
//i++;
//if(Q.rear == Q.frot) printf("相等\n");
}
}
printf("\n");
return;
} // 层次遍历二叉树
void InitStack(Stack &S){
S.base = (BiTree * )malloc(STACK_INIT_SIZE * sizeof(BiTree));
if(!S.base) return;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return;
} // 初始化栈
void PushStack(Stack &S, BiTree &BiTNode){
if((int)(S.top - S.base) >= S.stacksize){
S.base = (BiTree * )realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(BiTree));
if(!S.base)return;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top = BiTNode;
S.top++;
return;
} // 入栈
BiTree PopStack(Stack &S){
BiTree p;
if(S.top != S.base){
p = * --S.top;
}
return p;
//if(S.base == S.top){
//printf("栈为空!\n");
//return;
//}
//S.top--;
//return S;
//BiTree p;
//if(S.base != S.top){
//p = *(S.top - 1);
//printf("get\n");
//Visit(p->data);
//printf("\n");
//return p;
//}
} // 出栈
BiTree GetTopStack(Stack &S){
BiTree p;
p = *(S.top - 1);
return p;
//BiTree e;
//scanf("%d",&e);
//while(e != -1){
// PushStack(S, e);
// scanf("%d", &e);
//}
//return;
} // 取栈顶元素
void InitLinkQueue(LinkQueue &Q){
//Q.frot = (QNodeLink)malloc(sizeof(QNode));
//if(!Q.frot) return;
//Q.rear = Q.frot;
//Q.rear->next = NULL;
//return;
Q.frot = Q.rear = (QNodeLink)malloc(sizeof(QNode));
if(!Q.frot) return;
Q.frot->next = NULL;
return;
} // 构造一个空队列
void EnQueue(LinkQueue &Q, BiTree T){
//QNodeLink temp = (QNodeLink)malloc(sizeof(QNode));
//if(!temp) return;
//temp->pBiTNode = T;
//Q.rear->next = temp;
//temp->next = NULL;
//Q.rear = temp;
//return;
//printf("入队\n");
QNodeLink p = (QNodeLink)malloc(sizeof(QNode));
if(!p) return;
p->pBiTNode = T;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return;
} // 入队操作
BiTree DeQueue(LinkQueue &Q){
//if(Q.frot == Q.rear){
// printf("队列为空!\n");
//return;
//} //QNodeLink p, h;
//h = Q.frot;
//p = h->next;
//h->next = h->next->next;
//return;
//printf("出队\n");
QNodeLink p;
p = Q.frot->next;
BiTree e;
e = p->pBiTNode;
Q.frot->next = p->next;
if(Q.rear == p) Q.rear = Q.frot;
free(p);
//printf("出队结束\n");
return e;
} // 出队操作
掌握赫夫曼树的基本操作。参照主函数,补全各操作函数。
赫夫曼树(或哈夫曼树)又称最优二叉树,它是树的带权路径长度值为最小的二叉树,可用于构造最优编码,在信息传输、数据压缩等方面有着广泛的应用。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define N 100
#define MAX 10000
typedef struct
{
unsigned int weight;
unsigned int parent, lchild, rchild;
}HTNode, *HuffmanTree; //动态分配数组存储赫夫曼树
typedef char **HuffmanCode; //动态分配数组存储赫夫曼编码表
void CreatHuffmanTree(HuffmanTree &HT, unsigned int *w, int n); //构造赫夫曼树
void Select(HuffmanTree &HT, int k, int &s1, int &s2); //选择权值最小的节点
void PrintHuffmanTree(HuffmanTree &HT, char *ch, int n); //打印赫夫曼树
void EncodingHuffmanCode(HuffmanTree &HT, HuffmanCode &HC, int n); //构造赫夫曼编码表
void PrintHuffmanCode(HuffmanCode &HC, char *ch, int n); //打印赫夫曼编码表
void DecodingHuffmanCode(HuffmanTree &HT, char *ch, char *TestStr, int len, char *result, int n); //解码(译码)
int main()
{
HuffmanTree HT;
HuffmanCode HC;
char ch[N+1]; //0号单元不使用,存储n个等待编码的字符
unsigned int w[N+1]; //0号单元不使用,存储n个字符对应的权值
int n;
scanf("%d", &n);getchar();
for(int i = 1; i <= n; i++)
{
scanf("%c %d", &ch[i], &w[i]);
getchar();
}
char TestStr[N], result[N];
scanf("%s", TestStr);
CreatHuffmanTree(HT, w, n);
PrintHuffmanTree(HT, ch, n);
EncodingHuffmanCode(HT, HC, n);
PrintHuffmanCode(HC, ch, n);
int TestStrLen = strlen(TestStr);
DecodingHuffmanCode(HT, ch, TestStr, TestStrLen, result, n);
printf("编码%s对应的字符串是:%s\n", TestStr, result);
return 0;
}
void CreatHuffmanTree(HuffmanTree &HT, unsigned int *w, int n){
//printf("crearhead\n");
if(n <= 1) return;
int m = 2 * n - 1;
int s1, s2;
HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
for(int i = 1;i <= n; i++){
HT[i].weight = w[i];
HT[i].parent = 0;
HT[i].rchild = 0;
HT[i].lchild = 0;
}
for(int i = n + 1; i <= m; i++){
HT[i].parent = 0;
HT[i].rchild = 0;
HT[i].lchild = 0;
HT[i].weight = 0;
}
for(int i = n + 1; i <= m; i++){
Select(HT, i - 1, s1, s2);
HT[s1].parent = i;
HT[s2].parent = i;
HT[i].lchild = s1;
HT[i].rchild = s2;
HT[i].weight = HT[s1].weight + HT[s2].weight;
}
//printf("creatend\n");
return;
} //构造赫夫曼树
void Select(HuffmanTree &HT, int k, int &s1, int &s2){
unsigned int temp = MAX;
for(int i = 1; i <= k; i++){
if(HT[i].parent == 0){
if(temp > HT[i].weight){
temp = HT[i].weight;
s1 = i;
}
}
}
temp = MAX;
for(int i = 1; i <= k; i++){
if(HT[i].parent == 0 && i != s1){
if(temp > HT[i].weight){
temp = HT[i].weight;
s2 = i;
}
}
}
if(s2 < s1){
int temp = s2;
s2 = s1;
s1 = temp;
}
return;
} //选择权值最小的节点
void PrintHuffmanTree(HuffmanTree &HT, char *ch, int n)
{
printf("id,data,weight,parent,lchild,rchild\n");
for(int i = 1; i <= 2 * n - 1; i++)
{
if(i <= n)
printf("%2d:%2c,%6d,%6d,%6d,%6d\n", i, ch[i], HT[i].weight, \
HT[i].parent, HT[i].lchild, HT[i].rchild);
else
printf("%2d:--,%6d,%6d,%6d,%6d\n", i, HT[i].weight, \
HT[i].parent, HT[i].lchild, HT[i].rchild);
}
return;
}
void EncodingHuffmanCode(HuffmanTree &HT, HuffmanCode &HC, int n){
//printf("encodinghead\n");
HC = (HuffmanCode)malloc((n + 1) * sizeof(char *));
char *cd = (char *)malloc(n * sizeof(char));
cd[n - 1] = '\0';
int start;
unsigned int f, c;
//printf("forhead\n");
for(int i = 1; i <= n; i++){
//printf("%d ",i);
start = n - 1;
for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent){
//printf("%d ",f);
if(HT[f].lchild == c)
cd[--start] = '0';
else
cd[--start] = '1';
//break;
}
//puts(cd);
HC[i] = (char *)malloc((n - start) * sizeof(char));
strcpy(HC[i], &cd[start]);
}
free(cd);
//printf("\nencodingend\n");
return;
} //构造赫夫曼编码表
void PrintHuffmanCode(HuffmanCode &HC, char *ch, int n)
{
for(int i = 1; i <= n; i++)
printf("%c:%s\n", ch[i], HC[i]);
return;
}
void DecodingHuffmanCode(HuffmanTree &HT, char *ch, char *TestStr, int len, char *result, int n){
int p = 2 * n - 1;
int i = 0, j = 0;
for(i = 0; i < len; i++){
if(TestStr[i] == '0'){
p = HT[p].lchild;
}
if(TestStr[i] == '1'){
p = HT[p].rchild;
}
if(p <= n){
result[j] = ch[p];
j++;
p = 2 * n - 1;
}
}
result[j] = '\0';
return;
} //解码(译码
掌握用 C 语言实现图的创建和遍历的基本方法。参照main函数,补全各操作函数。
图(Graph)是一种较线性表和树更复杂的数据结构。
#include <stdio.h>
#include <malloc.h>
#define MAX_VERTEX_NUM 100
typedef char VertexType;
//图的邻接表存储表示
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
VertexType data;
ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vexnum, arcnum;
int kind;
}ALGraph;
//循环队列的存储表示
typedef struct
{
int v[MAX_VERTEX_NUM];
int frot, rear;
}SqQueue;
void InitSqQueue(SqQueue &Q); // 构造一个空队列
void EnSqQueue(SqQueue &Q, int v); // 入队操作
int DeSqQueue(SqQueue &Q); // 出队操作
void CreatALG(ALGraph &G); //构造图
int LocateVex(ALGraph &G, VertexType ch); //图的顶点定位
void PrintALG(ALGraph &G); //打印链接表(已知)
void DFSTraverse(ALGraph &G); //深度优先遍历图
void DFS(ALGraph &G, int i);
void BFSTraverse(ALGraph &G); //广度优先遍历图
int visited[MAX_VERTEX_NUM]; //访问标识数组,全局变量
int main()
{
ALGraph G;
CreatALG(G);
printf("------------------------------\n");
if(G.kind == 0)
printf("无向图的顶点数:%d\n无向图的弧数:%d\n", G.vexnum, G.arcnum);
else
printf("有向图的顶点数:%d\n有向图的弧数:%d\n", G.vexnum, G.arcnum);
printf("------------------------------\n");
printf("图的邻接表:\n\n");
PrintALG(G);
printf("------------------------------\n");
printf("图的深度优先遍历序列:");
DFSTraverse(G);
printf("\n------------------------------\n");
printf("图的广度优先遍历序列:");
BFSTraverse(G);
printf("\n------------------------------\n");
return 0;
}
/* 补全关键函数 */
void CreatALG(ALGraph &G)
{
VertexType ch;
int i = 0, s = 0;
scanf("%d", &G.kind);
getchar();
while((ch = getchar()) != '\n')
{
G.vertices[i].data = ch;
G.vertices[i].firstarc = NULL;
i++;
}
G.vexnum = i;
for(i = 0; i < G.vexnum; i++)
{
while((ch = getchar()) != '\n')
{
ArcNode *temp = (ArcNode *)malloc(sizeof(ArcNode));
temp->adjvex = LocateVex(G, ch);
temp->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = temp;
s++;
}
}
if(G.kind == 0)
G.arcnum = s / 2;
else
G.arcnum = s;
return;
}
int LocateVex(ALGraph &G, VertexType ch)
{
for(int i=0; i<G.vexnum; i++)
{
if(G.vertices[i].data == ch)
return i;
}
return -1;
}
void DFSTraverse(ALGraph &G)
{
for(int i = 0; i < G.vexnum; i++)
{
visited[i] = 0;
}
for(int i = 0; i < G.vexnum; i++)
{
if(!visited[i])
DFS(G, i);
}
}
void DFS(ALGraph &G, int i)
{
visited[i] = 1;
printf("%c", G.vertices[i].data);
for(ArcNode *temp = G.vertices[i].firstarc; temp; temp = temp->nextarc)
{
if(!visited[temp->adjvex])
DFS(G, temp->adjvex);
}
}
void BFSTraverse(ALGraph &G)
{
int i, index;
SqQueue Q;
InitSqQueue(Q);
for(i = 0; i < G.vexnum; i++)
visited[i] = 0;
for(i = 0; i < G.vexnum; i++)
{
if(!visited[i])
{
visited[i] = 1;
printf("%c", G.vertices[i].data);
EnSqQueue(Q, i);
while(Q.rear != Q.frot)
{
index = DeSqQueue(Q);
for(ArcNode *p = G.vertices[index].firstarc; p; p = p->nextarc)
{
if(!visited[p->adjvex])
{
visited[p->adjvex] = 1;
printf("%c", G.vertices[p->adjvex].data);
EnSqQueue(Q, p->adjvex);
}
}
}
}
}
}
void PrintALG(ALGraph &G)
{
ArcNode *temp;
if(G.vexnum == 0)
{
printf("图为空!\n");
return;
}
for(int i = 0; i < G.vexnum; i++)
{
printf("[%d]%c->", i, G.vertices[i].data);
temp = G.vertices[i].firstarc;
while(temp)
{
printf("[%d]->", temp->adjvex);
temp = temp->nextarc;
}
printf("NULL\n");
}
return;
}
void InitSqQueue(SqQueue &Q)
{
Q.frot = Q.rear = 0;
return;
}
void EnSqQueue(SqQueue &Q, int v)
{
if((Q.rear+1) % MAX_VERTEX_NUM == Q.frot)
{
printf("队列满,入队失败!\n");
return;
}
Q.v[Q.rear] = v;
Q.rear = (Q.rear+1)%MAX_VERTEX_NUM;
return;
}
int DeSqQueue(SqQueue &Q)
{
if(Q.frot == Q.rear)
return -1;
int temp = Q.v[Q.frot];
Q.frot = (Q.frot+1)%MAX_VERTEX_NUM;
return temp;
}
掌握用 C 语言实现求解无向网的最小生成树的基本方法。参照main函数,补全各操作函数。
生成树:一个连通图的生成树是指一个极小连通子图,含有图中的全部n个顶点,但只有足以构成一棵树的n-1条边。
#include <stdio.h>
#include <malloc.h>
#include <limits.h>
#define INFINITY INT_MAX //无穷大
#define MAX_VERTEX_NUM 100 //图中最大顶点数
typedef char VertexType; //顶点类型
typedef int VRType; //权值类型
/* 补全数据结构 */
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];
VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum, arcnum;
}MGraph;
typedef struct
{
VertexType adjvex;
VRType lowcost;
}Closedge;
typedef struct
{
int vstart;
int vend;
int w;
}Edge;
void CreateUDN(MGraph &G); //创建无向网
void PrintUDN(MGraph &G); //打印输出无向网
void MiniSpanTree_Prim(MGraph &G,VertexType u); //普里姆算法求解最小生成树
int LocateVex(MGraph &G, VertexType v); //定位节点v的下标
void MiniSpanTree_Kruskal(MGraph &G); //克鲁斯卡尔算法求解最小生成树
void InsertSort(Edge E[], int n); //排序
int main(void)
{
MGraph G;
CreateUDN(G);
VertexType v;
scanf("%c",&v);
PrintUDN(G);
printf("------------------------------\n");
printf("Prim算法求解由顶点%c出发生成的最小生成树:\n\n", v);
MiniSpanTree_Prim(G, v);
printf("------------------------------\n");
printf("Kruskal算法求解最小生成树:\n\n");
MiniSpanTree_Kruskal(G);
return 0;
}
/* 补全关键函数 */
void CreateUDN(MGraph &G)
{
int i=0, j, k, w;
char v1, v2;
scanf("%d %d", &G.vexnum, &G.arcnum);
getchar();
while((v1 = getchar()) != '\n')
G.vexs[i++] = v1;
for(i=0; i<G.vexnum; i++)
{
for(j=0; j<G.vexnum; j++)
G.arcs[i][j] = INFINITY;
}
for(k=0; k<G.arcnum; k++)
{
scanf("%c%c %d", &v1, &v2, &w);
getchar();
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j] = w;
G.arcs[j][i] = w;
}
return;
}
void MiniSpanTree_Prim(MGraph &G,VertexType u)
{
int i, j, k, mincost;
Closedge closedge[G.vexnum];
k = LocateVex(G, u);
for(i=0; i<G.vexnum; i++)
{
if(i != k)
{
closedge[i].adjvex = u;
closedge[i].lowcost = G.arcs[k][i];
}
}
closedge[k].lowcost = 0;
for(i=1; i<G.vexnum; i++)
{
mincost = INFINITY;
for(j=0; j<G.vexnum; j++)
{
if(closedge[j].lowcost < mincost && closedge[j].lowcost != 0)
{
mincost = closedge[j].lowcost;
k = j;
}
}
printf("[%c]--%d--[%c]\n", closedge[k].adjvex, mincost, G.vexs[k]);
closedge[k].lowcost = 0;
for(j=0; j<G.vexnum; j++)
{
if(G.arcs[k][j] < closedge[j].lowcost)
{
closedge[j].adjvex = G.vexs[k];
closedge[j].lowcost = G.arcs[k][j];
}
}
}
}
void MiniSpanTree_Kruskal(MGraph &G)
{
int i, j, vstart, vend, s_vstart, s_vend, k;
int vset[G.vexnum];
Edge E[G.arcnum];
k = 0;
for(i=0; i<G.vexnum-1; i++)
{
for(j=i+1; j<G.vexnum; j++)
{
if(G.arcs[i][j] != 0 && G.arcs[i][j] != INFINITY)
{
E[k].vstart = i;
E[k].vend = j;
E[k].w = G.arcs[i][j];
k++;
}
}
}
InsertSort(E, G.arcnum);
for(i=0; i<G.arcnum; i++)
vset[i] = i;
k = 1;
j = 0;
while(k < G.vexnum)
{
vstart = E[j].vstart;
vend = E[j].vend;
s_vstart = vset[vstart];
s_vend = vset[vend];
if(s_vstart != s_vend)
{
printf("[%c]--%d--[%c]\n", G.vexs[vstart], E[j].w, G.vexs[vend]);
for(i=0; i<G.vexnum; i++)
{
if(vset[i] == s_vend)
vset[i] = s_vstart;
}
k++;
}
j++;
}
}
void PrintUDN(MGraph &G)
{
if(G.vexnum == 0)
{
printf("图为空!\n");
return;
}
int i, j;
printf("------------------------------\n");
printf("顶点向量:\n\n");
for (i = 0; i < G.vexnum; i++)
{
printf("[%d]%c\n", i, G.vexs[i]);
}
printf("------------------------------\n");
printf("邻接矩阵:\n\n");
printf("%3c", '-');
for(i = 0; i < G.vexnum; i++)
printf("%3d", i);
printf("\n");
for (i = 0; i < G.vexnum; i++) //输出邻接矩阵
{
printf("%3d", i);
for (j = 0; j < G.vexnum; j++)
{
if (G.arcs[i][j] == INFINITY) //节点不连通时,输出'#'代表无穷大
printf("%3c", '#');
else //节点连通时,输出边上权值
printf("%3d", G.arcs[i][j]);
}
printf("\n");
}
}
int LocateVex(MGraph &G, VertexType v)
{
for (int i = 0; i < G.vexnum; i++)
{
if (G.vexs[i] == v)
return i;
}
return -1;
}
void InsertSort(Edge E[], int n)
{
int i, j;
Edge temp;
for(i = 1; i < n; i++)
{
temp = E[i];
j = i - 1;
while(j >= 0 && temp.w < E[j].w)
{
E[j + 1] = E[j];
j--;
}
E[j + 1] = temp;
}
}
掌握用 C 语言实现对AOE-网求解关键路径的基本方法。参照main函数,补全各操作函数。
在有向网中,如果用顶点表示事件,用有向边表示活动,边上的权值表示活动持续的时间,
#include <stdio.h>
#include <malloc.h>
#define MAX_VERTEX_NUM 100
typedef char VertexType;
//图的邻接表存储表示
/* 补全数据结构 */
typedef struct ArcNode
{
int adjvex;
int weight;
struct ArcNode*nextarc;
}ArcNode;
typedef struct VNode
{
int indegree;
VertexType data;
ArcNode*firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vexnum,arcnum;
}ALGraph;
typedef struct LNode
{
int data;
struct LNode *next;
}LStackNode,*LinkStack;
void CreateDN(ALGraph &G);
int LocateVex(ALGraph &G, VertexType ch);//已知
void PrintDN(ALGraph &G);//已知
int TopologicalSort(ALGraph &G, int T[], int ve[]);
void CriticalPath(ALGraph &G);
void InitStack(LinkStack &Top);//已知
void PushStack(LinkStack &Top, int e);//已知
int PopStack(LinkStack &Top);//已知
int main()
{
ALGraph G;
CreateDN(G);
printf("------------------------------\n");
printf("图的邻接表:\n\n");
PrintDN(G);
printf("------------------------------\n");
CriticalPath(G);
printf("------------------------------\n");
return 0;
}
/* 补全关键函数 */
void CreateDN(ALGraph &G)
{
VertexType v1,v2;
int i=0,vstart,vend,w;
scanf("%d %d",&G.vexnum,&G.arcnum);getchar();
while((v1=getchar())!='\n')
{
G.vertices[i].data=v1;
G.vertices[i].firstarc=NULL;
G.vertices[i].indegree=0;
i++;
}
for(i=0;i<G.arcnum;i++)
{
scanf("%c %c %d",&v1,&v2,&w);getchar();
vstart=LocateVex(G,v1);
vend=LocateVex(G,v2);
ArcNode *temp=(ArcNode *)malloc(sizeof(ArcNode));
temp->adjvex=vend;
temp->weight=w;
temp->nextarc=G.vertices[vstart].firstarc;
G.vertices[vstart].firstarc=temp;
G.vertices[vend].indegree++;
}
return;
}
int LocateVex(ALGraph &G, VertexType ch)
{
for(int i = 0; i < G.vexnum;i++)
{
if(G.vertices[i].data == ch)
return i;
}
return -1;
}
void PrintDN(ALGraph &G)
{
ArcNode *temp;
if(G.vexnum == 0)
{
printf("图为空!\n");
return;
}
for(int i = 0; i < G.vexnum; i++)
{
temp = G.vertices[i].firstarc;
printf("[%d]%c(%d)",i,G.vertices[i].data, G.vertices[i].indegree);
while(temp)
{
printf("-%d->[%d]", temp->weight, temp->adjvex);
temp = temp->nextarc;
}
printf("-->NULL\n");
}
return;
}
int TopologicalSort(ALGraph &G,int T[], int ve[])
{
int i,vcount,k;
LinkStack S;
InitStack(S);
ArcNode *p;
for(i=0; i<G.vexnum;i++)
{
if(G.vertices[i].indegree==0)
PushStack(S, i);
ve[i] = 0;
}
vcount= 0;
printf("拓扑排序有向图:");
while(S->next!=NULL)
{
i=PopStack(S);
T[vcount] =i;
printf("%c",G.vertices[i].data);
vcount++;
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
if((--G.vertices[k].indegree)==0)
PushStack(S,k);
if(ve[k] < ve[i] + p->weight)
ve[k] = ve[i] + p->weight;
}
}
if(vcount<G.vexnum)
{
printf("\n拓扑排序失败,有向网中有环路!\n");
return 0;
}
else
return 1;
}
void CriticalPath(ALGraph &G)
{
int i,j,k;
int v_early[G.vexnum],v_late[G.vexnum],topo[G.vexnum];
int e_early[G.arcnum],e_late[G.arcnum];
ArcNode *p;
if(!TopologicalSort(G,topo,v_early))
return;
for(i=0;i<G.vexnum;i++)
v_late[i] =v_early[G.vexnum-1];
for(i=G.vexnum-1;i>=0;i--)
{
k=topo[i];
for(p=G.vertices[k].firstarc;p;p=p->nextarc)
if(v_late[k]>v_late[p->adjvex]-p->weight)
v_late[k]=v_late[p->adjvex]-p->weight;
}
printf("\n\nAOE-网的关键路径:\n\n");
printf("顶点 v_early v_late\n");
for(i=0;i<G.vexnum;i++)
printf("%c%10d%10d\n", G.vertices[i].data, v_early[i],v_late[i]);
printf("\n活动 e_early e_late 关键路径\n");
for(i=0;i<G.vexnum;i++)
{
for(p = G.vertices[i].firstarc;p;p=p->nextarc)
{
e_early[i]=v_early[i];
e_late[i]=v_late[p->adjvex]-p->weight;
printf("%c-->%c%8d%10d", G.vertices[i].data, G.vertices[p->adjvex].data,e_early[i],e_late[i]);
if(e_early[i]==e_late[i])
printf("%10c\n", '*');
else
printf("%10c\n", '-');
}
}
return;
}
void InitStack(LinkStack &Top)
{
Top = (LinkStack)malloc(sizeof(LNode));
if(!Top) return;
Top->next = NULL;
}
void PushStack(LinkStack &Top, int e)
{
LinkStack newbase = (LinkStack)malloc(sizeof(LNode));
if(!newbase)
{
printf("内存空间分配失败!\n");
return;
}
newbase->data = e;
newbase->next = Top->next;
Top->next = newbase;
return;
}
int PopStack(LinkStack &Top)
{
LinkStack p = Top->next;
if(!p)
{
return 0;
}
Top->next = p->next;
int e = p->data;
free(p);
return e;
}
利用 C 语言实现静态查找表(顺序查找和折半查找)的基本方法。参照main函数,补全各操作函数。
顺序查找
#include <stdio.h>
#include <malloc.h>
#include <string.h>
typedef char KeyType;
typedef struct
{
KeyType key[10];
int score;
}ElemType; //元素类型
typedef struct
{
ElemType *elem;
int length;
}SSTable; //静态查找表的顺序存储结构
void Create_ST(SSTable &ST); //创建顺序查找表
void Search_Seq(SSTable &ST, KeyType key[]); //顺序查找
void Search_Bin(SSTable &ST, KeyType key[]); //折半查找
int main()
{
SSTable ST;
KeyType key[10];
Create_ST(ST);
scanf("%s", key);
printf("---------------静态查找---------------\n");
printf("顺序查找......\n");
Search_Seq(ST, key);
printf("\n折半查找......\n");
Search_Bin(ST, key);
return 0;
}
void Create_ST(SSTable &ST)
{
int i, n;
scanf("%d", &n);getchar();
ST.elem = (ElemType *)malloc((n + 1) * sizeof(ElemType));
if(!ST.elem) return;
for(i = 1; i <= n; i++)
scanf("%s %d", ST.elem[i].key, &ST.elem[i].score);
ST.length = n;
return;
}
void Search_Seq(SSTable &ST, KeyType key[])
{
int i,time=1;
strcpy(ST.elem[0].key,key);
for(i=ST.length;strcmp(ST.elem[i].key,key);i--,time++);
if(i!=0)
printf("查找成功!找到的值为:%d(比较的次数为:%d)\n",ST.elem[i].score,time);
else
printf("查找失败!(比较的次数为:%d)\n",time);
}
void Search_Bin(SSTable &ST, KeyType key[])
{
int low = 1,mid,high=ST.length,time = 1;
while(low <= high)
{
mid = (low + high)/2;
if(!strcmp(ST.elem[mid].key,key))
{
printf("查找成功!找到的值为:%d(比较的次数为:%d)\n",ST.elem[mid].score,time);
return;
}
else if(strcmp(ST.elem[mid].key,key) <0)
{
low = mid+1;
time++;
}
else
{
high = mid - 1;
time++;
}
}
printf("查找失败!(比较的次数为:%d)\n",time);
}
利用 C 语言实现动态查找表(二叉排序树)的基本方法。参照main函数,补全各操作函数。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MAX 100
typedef char KeyType;
typedef struct
{
KeyType key[10];
int price;
}ElemType; //元素类型
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree; //二叉排序树
void Create_BT(BiTree &T); //创建二叉排序树
int SearchBST(BiTree T, KeyType key[], BiTree f, BiTree &p); //二叉排序树查找
int Search_BST(BiTree T,KeyType key[], BiTree &p); //二叉排序树非递归查找
int InsertBST(BiTree &T, ElemType &e); //在二叉排序树中插入一个结点
void InOrderTraverse(BiTree &T); // 中序遍历二叉树
int number=0;
int main()
{
BiTree T = NULL, p;
KeyType key[10];
Create_BT(T);
scanf("%s", key);
printf("---------------二叉排序树查找---------------\n");
printf("中序遍历二叉排序树:\n");
InOrderTraverse(T);
number = 0;
printf("\n二叉排序树递归算法......\n");
if(SearchBST(T, key, NULL, p))
printf("查找成功!找到的值为:%d(比较的次数为:%d)\n",p->data.price, number);
else
printf("查找失败!(比较的次数为:%d)\n", number);
printf("\n二叉排序树非递归算法......\n");
number = 0;
if(Search_BST(T, key, p)) //非递归算法
printf("查找成功!找到的值为:%d(比较的次数为:%d)\n",p->data.price, number);
else
printf("查找失败!(比较的次数为:%d)\n", number);
return 0;
}
void InOrderTraverse(BiTree &T) // 中序遍历二叉树
{
if(T)
{
InOrderTraverse(T->lchild);
printf("%s %d\n", T->data.key, T->data.price);
InOrderTraverse(T->rchild);
}
}
void Create_BT(BiTree &T)
{
int n;
ElemType e;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%s %d", e.key, &e.price);
InsertBST(T, e);
}
}
int SearchBST(BiTree T, KeyType key[], BiTree f, BiTree &p)
{
number++;
if(!T)
{
p = f;
return 0;
}
else if(strcmp(T->data.key, key) == 0)
{
p = T;
return 1;
}
else if(strcmp(key, T->data.key) < 0)
return SearchBST(T->lchild, key, T, p);
else
return SearchBST(T->rchild, key, T, p);
}
int InsertBST(BiTree &T, ElemType &e)
{
BiTree p, s;
//if(!Search_BST(T, e.key, p))//
if(!SearchBST(T, e.key, NULL, p))
{
s = (BiTNode *)malloc(sizeof(BiTNode));
strcpy(s->data.key, e.key);
s->data.price = e.price;
s->lchild = s->rchild = NULL;
if(!p)
T = s;
else if(strcmp(e.key, p->data.key)<0)
p->lchild = s;
else
p->rchild = s;
return 1;
}
else return 0;
}
int Search_BST(BiTree T, KeyType key[], BiTree &p)
{
number++;
BiTree q;
if(!T)
{
p = T;
return 0;
}
q = T;
while(q)
{
if(strcmp(q->data.key, key) == 0)
{
p = q;
return 1;
}
else if(strcmp(q->data.key, key) > 0)
{
p = q;
q = q->lchild;
number++;
}
else
{
p = q;
q = q->rchild;
number++;
}
}
return 0;
}
掌握用 C 语言实现 Hash 表(开放地址法)基本操作的方法。参照main函数,补全各操作函数。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define HASHSIZE 11 //哈希表的长度
#define M 11 //定义除余数法中的质因子
#define NULLKEY 0 //定义空关键字
#define SUCCESS 1 //查找成功
#define UNSUCCESS 0 //查找失败
#define DUPLICATE -1 //哈希表中已有相同关键字的元素
typedef int KeyType;
typedef struct
{
KeyType key;
char other[10];
}ElemType;
//开放地址法,线性探测再散列
typedef struct
{
ElemType r[HASHSIZE];
int length;
}HashTalbe;
int p, c; //全局变量哈希地址和探测次数
int Hash(int p); //哈希函数
int SearchHash(HashTalbe &H, KeyType key); //查找操作
int InsertHash(HashTalbe &H, ElemType &e); //插入操作
void PrintHashTable(HashTalbe &H); //打印输出哈希表
int main()
{
HashTalbe H;
ElemType e;
int n;
for(int i = 0; i < HASHSIZE; i++)
H.r[i].key = NULLKEY;
scanf("%d", &n);
while(n--)
{
scanf("%d %s", &e.key, e.other);
InsertHash(H, e);
}
PrintHashTable(H);
printf("哈希表的插入操作时最大探测次数为:%d", c);
return 0;
}
void PrintHashTable(HashTalbe &H)
{
int i;
printf("哈希表为(* 代表空值):\n");
for(i = 0; i < HASHSIZE; i++)
printf("%5d", i);
printf("\n");
for(i = 0; i <= 5 * HASHSIZE; i++)
printf("-");
printf("\n");
for(i = 0; i < HASHSIZE; i++)
{
if(H.r[i].key != NULLKEY)
printf("|%4d", H.r[i].key);
else
printf("|%4c", '*');
}
printf("|\n");
for(i = 0; i <= 5 * HASHSIZE; i++)
printf("-");
printf("\n");
for(int i = 0; i < HASHSIZE; i++)
{
if(H.r[i].key != NULLKEY)
printf("|%s", H.r[i].other);
else
printf("|%4c", ' ');
}
printf("|\n");
for(i = 0; i <= 5 * HASHSIZE; i++)
printf("-");
printf("\n");
}
int Hash(int p)
{
return p % M;
}
int SearchHash(HashTalbe &H, KeyType key)
{
int i = 0;
p = Hash(key);
while(H.r[p].key != NULLKEY && key != H.r[p].key)
{
p = (p + 1) % M;
i++;
}
if(i > c)
c = i;
if(key == H.r[p].key)
return SUCCESS;
else
return UNSUCCESS;
}
int InsertHash(HashTalbe &H, ElemType &e)
{
if(SearchHash(H, e.key) == SUCCESS)
return DUPLICATE;
H.r[p].key = e.key;
strcpy(H.r[p].other, e.other);
H.length++;
return 0;
}
插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 100
typedef int KeyType;
//typedef char InfoType;
typedef struct
{
KeyType key; //记录关键字
//InfoType otherinfo; //其他数据项
}RecordType;
typedef struct
{
RecordType r[MAXSIZE + 1];
int length;
}SqList;
int k;
void InsertSort(SqList &L); //直接插入排序
void ShellSort(SqList &L); //希尔排序,使用L.length/2作为增量dlta
void PrintSqList(SqList &L);
void CopySqList(SqList &L1, SqList &L2);
void CreateSqList(SqList &L);
int main(void)
{
SqList L1, L2;
CreateSqList(L1);
CopySqList(L1, L2);
printf("直接插入排序(插入排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
InsertSort(L2);
CopySqList(L1, L2);
printf("\n希尔排序(插入排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
k = 1;
ShellSort(L2);
return 0;
}
void CreateSqList(SqList &L)
{
scanf("%d", &L.length);
for(int i = 1; i <= L.length; i++)
scanf("%d", &L.r[i].key);
}
void PrintSqList(SqList &L)
{
for(int i = 1; i <= L.length; i++)
printf("%3d", L.r[i].key);
printf("\n");
}
void CopySqList(SqList &L1, SqList &L2)
{
L2.length = L1.length;
for(int i = 1;i <= L1.length; i++)
L2.r[i].key = L1.r[i].key;
return;
}
void InsertSort(SqList &L)
{
int j;
for(int i=2;i<=L.length;i++)
{
if(L.r[i].key<L.r[i-1].key)
{
L.r[0]=L.r[i];
L.r[i]=L.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];
}
printf("%2d趟排序的结果:",i-1);
PrintSqList(L);
}
}
void ShellSort(SqList &L)
{
int i,j,dk=L.length/2;
while(dk>0)
{
for(i=1+dk;i<=L.length;i++)
{
if(L.r[i].key<L.r[i-dk].key)
{
L.r[0] =L.r[i];
for(j=i-dk;j>0&&L.r[j].key>L.r[0].key;j-=dk)
L.r[j+dk]=L.r[j];
L.r[j+dk]=L.r[0];
}
}
printf("%2d趟排序的结果:",k++);
PrintSqList(L);
dk/=2;
}
}
起泡排序(Bubble Sort)是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 100
typedef int KeyType;
//typedef char InfoType;
typedef struct
{
KeyType key; //记录关键字
//InfoType otherinfo; //其他数据项
}RecordType;
typedef struct
{
RecordType r[MAXSIZE + 1];
int length;
}SqList;
int k;
void BubbleSort(SqList &L); //起泡排序
int Partition(SqList &L, int low, int high); //一趟快速排序算法
void QSort(SqList &L, int low, int high);
void QuickSort(SqList &L); //快速排序
void PrintSqList(SqList &L);
void CopySqList(SqList &L1, SqList &L2);
void CreateSqList(SqList &L);
int main(void)
{
SqList L1, L2;
CreateSqList(L1);
CopySqList(L1, L2);
printf("起泡排序(快速排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
BubbleSort(L2);
CopySqList(L1, L2);
printf("\n快速排序(快速排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
k = 1;
QuickSort(L2);
return 0;
}
void CreateSqList(SqList &L)
{
scanf("%d", &L.length);
for(int i = 1; i <= L.length; i++)
scanf("%d", &L.r[i].key);
return;
}
void PrintSqList(SqList &L)
{
for(int i = 1; i <= L.length; i++)
printf("%3d", L.r[i].key);
printf("\n");
}
void CopySqList(SqList &L1, SqList &L2)
{
L2.length = L1.length;
for(int i = 1;i <= L1.length; i++)
L2.r[i].key = L1.r[i].key;
return;
}
void BubbleSort(SqList &L)
{
int flag;
for(int i=0;i<L.length;i++)
{
flag=0;
for(int j=1;j<L.length-i;j++)
{
if(L.r[j].key>L.r[j+1].key)
{
L.r[0]=L.r[j+1];
L.r[j+1]=L.r[j];
L.r[j]=L.r[0];
flag=1;
}
}
if(!flag) return;
printf("%2d趟排序的结果:",i+1);
PrintSqList(L);
}
}
int Partition(SqList &L,int low,int high)
{
L.r[0]= L.r[low];
int pivotkey= L.r[low].key;
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];
}
L.r[low]= L.r[0];
printf("%2d趟排序的结果:",k++);
PrintSqList(L);
return low;
}
void QSort(SqList &L,int low,int high)
{
if(low<high){
int pos = Partition(L,low,high);
QSort(L,low,pos-1);
QSort(L,pos+1,high);
}
}
void QuickSort(SqList &L)
{
QSort(L,1,L.length);
}
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 100
typedef int KeyType;
//typedef char InfoType;
typedef struct
{
KeyType key; //记录关键字
//InfoType otherinfo; //其他数据项
}RecordType;
typedef struct
{
RecordType r[MAXSIZE + 1];
int length;
}SqList;
void SelectSort(SqList &L); //简单选择排序
void HeapAdjust(SqList &L, int s, int m);
void HeapSort(SqList &L); //堆排序
void PrintSqList(SqList &L);
void CopySqList(SqList &L1, SqList &L2);
void CreateSqList(SqList &L);
int main(void)
{
SqList L1, L2;
CreateSqList(L1);
CopySqList(L1, L2);
printf("简单选择排序(选择排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
SelectSort(L2);
CopySqList(L1, L2);
printf("\n堆排序(选择排序)......\n");
printf("排序前的顺序表:");
PrintSqList(L1);
HeapSort(L2);
return 0;
}
void CreateSqList(SqList &L)
{
scanf("%d", &L.length);
for(int i = 1; i <= L.length; i++)
scanf("%d", &L.r[i].key);
return;
}
void PrintSqList(SqList &L)
{
for(int i = 1; i <= L.length; i++)
printf("%3d", L.r[i].key);
printf("\n");
}
void CopySqList(SqList &L1, SqList &L2)
{
L2.length = L1.length;
for(int i = 1;i <= L1.length; i++)
L2.r[i].key = L1.r[i].key;
return;
}
void SelectSort(SqList &L)
{
int k=0;
for(int i=1;i<L.length;i++)
{
for(int j=i+1;j<=L.length;j++)
{
if(L.r[j].key<L.r[k].key)
k=j;
}
if( k!=i)
{
L.r[0]=L.r[i];
L.r[i]=L.r[k];
L.r[k]=L.r[0];
}
printf("%2d趟排序的结果:",i);
PrintSqList(L);
}
}
void HeapAdjust(SqList &L,int s,int m)
{
int i=s;
L.r[0]=L.r[i];
for(int j=2*i;j<=m;j*=2)
{
if(j<m&&L.r[j].key<L.r[j+1].key)
j++;
if(L.r[0].key>L.r[j].key)
break;
L.r[i]=L.r[j];
i=j;
}
L.r[i]=L.r[0];
}
void HeapSort(SqList &L)
{
int i,j=1;
for(i=L.length/2;i>0;i--)
{
HeapAdjust(L,i,L.length);
}
for(i=L.length;i>1;i--)
{
L.r[0]=L.r[1];
L.r[1]=L.r[i];
L.r[i]=L.r[0];
HeapAdjust(L,1,i-1);
printf("%2d趟排序的结果:",j++);
PrintSqList(L);
}
}