课后习题 https://www.cnblogs.com/kangjianwei101/category/791618.html
https://www.dotcpp.com/course/100
习题:https://blog.csdn.net/Eumenides_Suki/article/details/109959937
第一章 绪论
1 熟悉各名词、术语的含义,掌握基本概念。
数据,数据元素,数据对象,数据结构,逻辑结果,存储结构,数据类型,抽象数据类型
2 理解算法五个要素的确切含义。p13
有穷性,确定性,可行性,输入,输出
3. 掌握计算语句频度和估算算法时间复杂度的方法。p15
课后习题
https://www.cnblogs.com/kangjianwei101/p/5222150.html
第二章线性表
https://www.cnblogs.com/kangjianwei101/p/5223723.html
1.线性表的定义(逻辑结构及其特点)
顺序存储
2.熟练掌握线性表顺序存储结构的描述方法,以及线性表的各种操作的实现。(PPT上的算法)
3.从时间复杂度分析顺序存储结构的特点及适用场合。(记住插入、删除时间复杂度,优势)
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int ElementType;
typedef int Position;
//线性表的顺序存储实现
typedef struct LNode
{
ElementType Data[MAXSIZE]; //数组
Position Last;//长度
}*PtrToLNode;
typedef PtrToLNode List;
//初始化
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));
L->Last = -1;
return 0;
}
//查找
//查找成功的平均比较次数为(n +1)/2,平均时间性能为 O(n)。
Position Find(List L, ElementType x)
{
Position i = 0;
while (i <= L->Last && L->Data[i] != x) i++;
if (i > L->Last)
return -1;
else
return i;
}
//插入
//平均移动次数为 n /2,平均时间性能为 O(n)。
bool Insert(List L, ElementType X, int i)
{
Position j;
if (L->Last == MAXSIZE - 1) {
/* 表空间已满,不能插入 */
printf("表满");
return -1;
}
if (i<1 || i>L->Last + 2) {
/* 检查插入位序的合法性:是否在1~n+1。n为当前元素个数,即Last+1 */
printf("位序不合法");
return false;
}
for (j = L->Last; j >= i - 1; j--) /*Last指向序列最后元素 */
L->Data[j + 1] = L->Data[j]; /* 将位序i及以后的元素顺序向后移动 */
L->Data[i - 1] = X; /* 新元素插入第i位序,其数组下标为i-1 */
L->Last++; /* Last仍指向最后元素 */
return 1;
}
//删除
//平均移动次数为 (n-1) /2,平均时间性能为 O(n)。
bool Delete(List L, int i)
{
Position j;
if (i<1 || i>L->Last + 1) { /* 检查空表及删除位序的合法性 */
printf("位序%d不存在元素", i);
return false;
}
for (j = i; j <= L->Last; j++)
L->Data[j - 1] = L->Data[j]; /*将位序i+1及以后的元素顺序向前移动*/
L->Last--; /* Last仍指向最后元素 */
return true;
}
链式存储
4.熟练掌握线性表链式存储结构的描述方法,以及线性表的各种操作的实现。(PPT上的算法)
5.从时间复杂度分析链式存储结构的特点及适用场合。(优点和缺点)
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int ElementType;
typedef int Position;
//线性表的链式存储实现
typedef struct LNode* PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
//求表长
//时间性能为 O(n)。
int Length(List L)
{
Position p;
int cnt = 0; /* 初始化计数器 */
p = L; /* p指向表的第一个结点 */
while (p) {
p = p->Next;
cnt++; /* 当前p指向的是第cnt个结点*/
}
return cnt;
}
//查找
//平均时间性能为 O(n)。
//按序号查找
#define ERROR -1
ElementType FindKth(List L, int K)
{
Position p;
int cnt = 1; /* 位序从1开始 */
p = L; /* p指向L的第1个结点 */
while (p && cnt < K) {
p = p->Next;
cnt++;
}
if ((cnt == K) && p)
return p->Data; /* 找到第K个 */
else
return ERROR; /* 否则返回错误信息 */
}
//按值查找
Position Find(List L, ElementType X)
{
Position p = L;
/* p指向L的第1个结点 */
while (p && p->Data != X)
p = p->Next;
/* 下列语句可以用 return p; 替换 */
if (p)
return p;
else
return NULL;
}
//插入(在链表的第 i(1≤i≤n+1)个结点后插入一个值为X的新结点)
//平均查找次数为 n / 2,平均时间性能为 O(n)。
#define ERROR NULL /* 用空地址表示错误 */
List Insert(List L, ElementType X, int i)
{
Position tmp, pre;
tmp = (Position)malloc(sizeof(struct LNode)); /* 申请、填装结点 */
tmp->Data = X;
if (i == 1) { /* 新结点插入在表头 */
tmp->Next = L; return tmp; /* 返回新表头指针 */
}
else { /* 查找位序为i-1的结点 */
int cnt = 1; /* 位序从1开始 */
pre = L; /* pre指向L的第1个结点 */
while (pre && cnt < i - 1) {
pre = pre->Next; cnt++;
}
if (pre == NULL || cnt != i - 1) { /* 所找结点不在L中 */
printf("插入位置参数错误\n");
free(tmp); return ERROR;
}
else { /* 找到了待插结点的前一个结点pre */
tmp->Next = pre->Next;
pre->Next = tmp; return L;
}
}
}
//删除(删除链表的第 i (1≤i≤n)个位置上的结点
//平均查找次数为 n /2,平均时间性能为 O(n)。
bool Delete(List L, int i)
{ /* 这里默认L有头结点 */
Position tmp, pre;
int cnt = 0;
/* 查找位序为i-1的结点 */
pre = L; /* pre指向表头 */
while (pre && cnt < i - 1) {
pre = pre->Next;
cnt++;
}
if (pre == NULL || cnt != i - 1 || pre->Next == NULL) {
/* 所找结点或位序为i的结点不在L中 */
printf(“删除位置参数错误\n");
return false;
}
else { /* 找到了待删结点的前一个结点pre */
/* 将结点删除 */
tmp = pre->Next;
pre->Next = tmp->Next;
free(tmp);
return true;
}
}
循环链表 双链表 。。
6.单链表、循环链表、双链表的插入、删除、查找的实现语句。
循环:https://www.dotcpp.com/course/100
课后习题的算法 。。
2.11,2.12,2.14,2.19,2.21,2.22,2.24,2.25,2.26,2.31,2.33
https://www.cnblogs.com/kangjianwei101/p/5222655.html
2.24
第三章栈和队列
栈
3.1栈(定义及特点,课后习题,讨论题,顺序栈和链栈基本操作函数的实现)
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int ElementType;
typedef int Position;
//栈的顺序存储
typedef int Position;
typedef struct SNode* PtrToSNode;
struct SNode {
ElementType* Data; /* 存储元素的数组 */
Position Top; /* 栈顶指针 */
int MaxSize; /* 堆栈最大容量 */
};
typedef PtrToSNode Stack;
bool IsFull(Stack S)
{
return (S->Top == S->MaxSize - 1);
}
bool Push(Stack S, ElementType X)
{
if (IsFull(S)) {
printf("堆栈满"); return false;
}
else {
S->Data[++(S->Top)] = X;
return true;
}
}
bool IsEmpty(Stack S)
{
return (S->Top == -1);
}
ElementType Pop(Stack S)
{
if (IsEmpty(S)) {
printf("堆栈空");
return -1; /* ERROR是ElementType的特殊值,标志错误 */
}
else return (S->Data[(S->Top)--]);
}
+++
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 10
typedef int ElementType;
typedef int Position;
typedef struct SNode* PtrToSNode;
struct SNode {
ElementType Data;
PtrToSNode Next;
};
typedef PtrToSNode Stack;
Stack CreateStack()
{ /* 构建一个堆栈的头结点,返回该结点指针 */
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
bool IsEmpty(Stack S)
{ /* 判断堆栈S是否为空,若是返回true;否则返回false */
return (S->Next == NULL);
}
bool Push(Stack S, ElementType X)
{ /* 将元素X压入堆栈S */
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->Data = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
return true;
}
ElementType Pop(Stack S)
{ /* 删除并返回堆栈S的栈顶元素 */
PtrToSNode FirstCell;
ElementType TopElem;
if (IsEmpty(S)) {
printf("堆栈空"); return ERROR;
}
else {
FirstCell = S->Next;
TopElem = FirstCell->Data;
S->Next = FirstCell->Next;
free(FirstCell);
return TopElem;
}
}
3.2栈的应用举例(阶乘,括号匹配,表达式求值等的算法)
3.3栈与递归的实现(函数调用的过程,递归与栈之间的关系)
队列
3.4队列(定义及特点,课后习题,讨论题,队列的顺序存储的实现方法)
第四章 串
4.1串的类型定义
https://www.cnblogs.com/ahguSH/p/6218774.html
第五章数组和广义表
数组
5.1数组的定义(了解)
数组(Array)是有序的元素序列。 [1] 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。
5.2数组的顺序表示和实现p93(根据下标计算出存储的位置,低下表优先,高下标优先)
5.3数组的压缩存储(三元组的定义p97及存储p98的方式)(不要求算法)
广义表
5.4广义表的定义p108(熟练掌握定义,表的长度,表的深度,空表等)[ppt 线性结构a,
长度和深度:https://blog.csdn.net/fu_jian_ping/article/details/89281571
5.5广义表的存储结构(表头、表尾表示法,取表头,取表尾,存储结构p109的描述)
ppt03
5.6课后习题
第六章树和二叉树
https://max.book118.com/html/2020/1128/6145225222003025.shtm
树
6.1树的定义和基本术语(结点之间的关系,父子,兄弟,树的度,度的深度等,参考PPT)
二叉树
6.2二叉树(5种形态,二叉树的性质)
https://blog.csdn.net/cocoiehl/article/details/80959150
二叉树的遍历和线索二叉树
6.3遍历二叉树和线索二叉树(各种遍历,遍历算法,中序遍历的非递归算法,线索树的定义及会画出一棵线索树)
#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct TNode* Position;
typedef Position BinTree; /* 二叉树类型 */
struct TNode { /* 树结点定义 */
ElementType Data; /* 结点数据 */
BinTree Left; /* 指向左子树 */
BinTree Right; /* 指向右子树 */
};
void InOrderTraversal(BinTree BT)://根结点的访问次序在左、右子树之间;
void PreOrderTraversal(BinTree BT)://根结点的访问次序在左、右子树之前;
void PostOrderTraversal(BinTree BT)://根结点的访问次序在左、右子树之后 。
void LevelOrderTraversal(BinTree BT)://按层从小到大、从左到右的次序遍历。
void InOrderTraversal(BinTree BT)//中序
{
if (BT) {
InOrderTraversal(BT->Left);
printf(" %d", BT->Data);
InOrderTraversal(BT->Right);
}
}
void PreOrderTraversal(BinTree BT)
{
if (BT) {
printf(" %d", BT->Data);
PreOrderTraversal(BT->Left);
PreOrderTraversal(BT->Right);
}
}
void PostOrderTraversal(BinTree BT)
{
if (BT) {
PostOrderTraversal(BT->Left);
PostOrderTraversal(BT->Right);
printf(" %d ", BT->Data);
}
}
//--中序遍历非递归遍历算法--
//遇到一个结点,就把它压栈,并去遍历它的左子树;
//当左子树遍历结束后,从栈顶弹出这个结点并访问它;
//然后按其右指针再去中序遍历该结点的右子树。
void InorderTraversal(BinTree BT)
{
BinTree T;
Stack S = CreateStack();
T = BT; /* 从根结点出发 */
while (T || !IsEmpty(S)) {
while (T) { /* 一直向左并将沿途结点压入堆栈 */
Push(S, T);
T = T->Left;
}
T = Pop(S); /* 结点弹出堆栈 */
printf("%d ", T->Data); /*(访问)打印结点 */
T = T->Right; /* 转向右子树 */
}
}
树和森林
6.4树和森林(树和森林的遍历,树与二叉树之间的转换)
树和森林的遍历:https://blog.csdn.net/u011240016/article/details/52824161
树与二叉树之间的转换:https://www.cnblogs.com/youknowUL/articles/11546358.html
哈夫曼树
6.6哈夫曼树及其应用(给出条件会建立一棵哈夫曼树,并完成编码,哈夫曼树的性质,基本概念)
https://blog.csdn.net/qq_29519041/article/details/81428934
习题
这章的课后习题
第七章图
定义
7.1图的定义和术语(参考PPT)
存储
7.2图的存储结构(给出图,能够正确画出两种存储结构)
图的遍历
7.3 图的遍历(给出存储结构,能够得出两种遍历的结果,每种遍历应用的是栈还是队列,图的遍历算法)
连通图、强连通图 最小生成树
7.4图的连通性问题(连通图、强连通图的定义,最小生成树的定义,按照普里姆算法生成最小生成树的过程,按照克鲁斯卡尔算法生成最小生成树的过程)
无向图中,如果任意两个顶点之间都能够连通,则称此无向图为连通图
有向图中,若任意两个顶点 Vi 和 Vj,满足从 Vi 到 Vj 以及从 Vj 到 Vi 都连通,也就是都含有至少一条通路,则称此有向图为强连通图
拓扑排序 关键路径
7.5有向无环图及其应用 (拓扑排序的定义,给出一个图能够得出拓扑排序的结果,拓扑排序的算法,关键路径的求解方法,最早开始时间,最迟开始时间的求解,关键活动)
最短路径 迪杰斯特拉
7.6最短路径(掌握迪杰斯特拉算法的求解过程以及算法,按照书上表格可以,按照PPT上的过程也可以)
课后习题
第九章 查找
https://wenku.baidu.com/view/4472243d162ded630b1c59eef8c75fbfc67d94dd.html
静态查找
9.1 静态查找表(顺序查找的算法,监视哨的作用,折半查找)
动态查找 (树
9.2动态查找表
动态查找表包括二叉排序树、平衡二叉树(AVL树)、B树、B+树以及红黑树。
9.2.2二叉排序树(定义,性质,插入过程及算法,删除过程,删除不要求掌握算法)
懒猫
9.2.3平衡二叉树(定义,判断一棵树是否是平衡二叉树,如果不平衡,如何调整,不掌握算法)
https://blog.csdn.net/weixin_39963255/article/details/111093422
9.2.4 B_树(定义,性质,插入和删除过程,不要求掌握算法)
https://my.oschina.net/u/4116286/blog/3107389
插入:判断当前结点key的个数是否小于等于m-1,如果满足,直接插入即可,如果不满足,将节点的中间的key将这个节点分为左右两部分,中间的节点放到父节点中即可
哈希表
9.3哈希表(定义,特点,复杂度与什么相关,处理冲突的方法,除留余数法建立查找表)
课后习题
第十章 排序
基础
10.1概述(排序的基本概念,稳定性)
https://blog.csdn.net/qq_43152052/article/details/100078825
堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。
不稳定:选堆快希
插入排序
10.2插入排序(直接插入排序,希尔排序,排序过程,不要求算法)
快速排序
10.3 快速排序(起泡排序,快速排序(掌握算法))
选择排序
10.4 选择排序(简单选择排序,堆排序,不要求算法)
归并排序
10.5 归并排序(归并排序的过程,算法结合第2章理解)
基数排序
10.6基数排序(基数排序,链式基数排序的过程,不要求算法)
https://www.cnblogs.com/yimeixiaobai1314/p/7932254.html
相关
10.7各种排序方法讨论(很重要,参照PPT)
课后习题