下面知识点本次考试不设计题目:特殊矩阵存储、广义表、线索树、十字链表、邻接多重链表、最短路径的弗洛伊德算法、关键路径、平衡二叉树、B树、B+树、归并排序、基数排序、外部排序等原理和实现。
一
1. 数据结构的定义、逻辑结构和存储结构。
定义
数据结构是相互之间存在一种或多种特定关系的数据元素的集合 数据结构就是带结构的数据元素的集合 结构就是指数据元素间存在的关系
数据结构的层次
逻辑结构
- 线性结构 一对一
线性表 栈和队列 串和数组 - 非线性结构
树形结构 一对多 图形结构 多对多
储存结构
顺序存储——借助元素在存储器中的相对位置来表示数据元素间的逻辑关系 链式存储——借助指示元素存储的地址的指针表示数据元素间的逻辑关系
2. 时空复杂度分析
尤其是能熟练使用大O函数进行时间复杂度估算。
for(i=0;i<100000;i++)
i=1;
while(i<n)
i=i*2;
for(i=0;i<n;i++)
二.线性表
1. 线性表的顺序存储和链式存储的特点
顺序存储(随机存取):用地址连续的存储单元依次存放线性表中的数据元素(逻辑上和物理上都相邻 链式存储(顺序存取):用一组地址任意的存储单元存放线性表中的数据元素
2. 线性表的基本实现和操作
实现
顺序
typedef struct {
ElemType *elem;
int length;
} SqList;
链式
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode, *linkList;
linkList L=xxxx;
L = new LNode;
操作
线链表的插入、删除、查找、等算法
Status InitList(linkList &L)
{
L = new LNode;
L->next=NULL;
return OK;
}
Status InitList(linkList &L)
{
L = NULL;
return OK;
}
Status ListInsert(linkList &L, int i, ElemType e)
{
int j=0;
linkList p=L;
while(p&&j<i-1)
{
j++;
p=p->next
}
if(!p||j>i-1)
return 0;
linkList q = new LNode;
q->data=e;
q->next=p->next;
p->next=q;
return 1;
}
Status ListDelete(linkList &L, int i)
{
int j=0;
linkList p=L;
while(p&&j<i-1)
{
j++;
p = p->next;
}
if(!p||j>i-1)
return 0;
linkList q;
q = p->next;
p->next = q->next;
delete q;
return 1;
}
void CreateList_R(LinkList &L)
{
linkList p=L;
while(p->next)
{
p=p->next;
}
while(!cin >> ch)
{
linkList q = new LNode;
q->data=ch;
p->next=NULL;
p->next = q;
p=q;
}
}
三.栈和队列
1. 栈和队列的定义、操作特点
都是限制在表的一端进行插入和删除运算的线性表
- 栈 ( 先进后出):插入删除一端为栈顶,另一端为栈底
- 队列 (先进先出):在队尾插入,在队头删除
2.栈和队列的实现和基本操作
栈的实现和基本操作
定义实现
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
} SqStack;
typedef struct StackNode {
SElemType data;
struct StackNode *next;
} StackNode, *LinkStack;
操作(顺序栈)
因为链栈与线性表相似,所以不再写出
Status InitStack(SqStack &s)
{
s.base = new SElemType[MAXSIZE];
if(!s.base)
exit(0);
s.top=s.base;
s.stacksize = MAXSIZE;
}
void DestroyStack(SqStack &s)
{
delete []s.base;
s.base=s.top=NULL;
s.stacksize = 0;
}
Status Push(SqStack &s, SElemType e)
{
if(s.top-s.base==s.stacksize)
return 0;
else
{
*(s.top++)=e;
return OK;
}
}
SElemType GetTop(SqStack s)
{
if(s.base==s.top)
return 0;
else
{
return *(s.top-1);
}
}
队列的实现和基本操作
定义实现
在这里插入代码片
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
} LinkQueue;
操作
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
#define MAXQSIZE 6
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int QElemType;
typedef int Status;
typedef struct QNode {
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
} LinkQueue;
Status InitQueue(LinkQueue &q)
{
q.front = q.rear = new QNode;
q.front->next = NULL;
return OK;
}
void DestroyQueue(LinkQueue &q)
{
for(QueuePtr p = q.front, q; p; ) {
q = p->next;
delete p;
p = q;
}
}
Status QueueEmpty(LinkQueue q)
{
return q.rear==q.front;
}
int QueueLength(LinkQueue q)
{
int len=0;
QueuePtr p = q.front->next;
while(p)
{
p=p->next;
len++;
}
return len;
}
Status EnQueue(LinkQueue &q, QElemType e)
{
QueuePtr p = new QNode;
p->data=e;
p->next=NULL;
q.rear->next=p;
q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &q, QElemType &e)
{
if(q.rear==q.front)
return ERROR;
QueuePtr z;
z=q.front->next;
e=z->data;
q.front->next=z->next;
delete z;
return OK;
}
QElemType GetHead(LinkQueue q)
{
return q.front->next->data;
}
void PrintQueue(LinkQueue q)
{
QueuePtr p;
for(p = q.front->next; p; p = p->next) {
cout << p->data;
if(p->next != NULL)
cout << ' ';
}
cout << endl;
}
循环队列 队满条件: (q.rear+1)%MAXQSIZE==q.front 队列长度: q.rear-q.front+MAXQSIZE)%MAXQSIZE
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
#define MAXQSIZE 6
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int QElemType;
typedef int Status;
typedef struct {
QElemType *base;
int front;
int rear;
} SqQueue;
Status InitQueue(SqQueue &q)
{
q.base = new QElemType[MAXQSIZE];
if(!q.base)
exit(OVERFLOW);
q.front = q.rear = 0;
return OK;
}
void DestroyQueue(SqQueue &q)
{
if(q.base)
delete []q.base;
q.base = NULL;
q.front = q.rear = 0;
}
int QueueLength(SqQueue q)
{
return ((q.rear-q.front+MAXQSIZE)%MAXQSIZE);
}
bool QueueEmpty(SqQueue q)
{
return (q.front==q.rear);
}
Status EnQueue(SqQueue &q, QElemType e)
{
{
if((q.rear+1)%MAXQSIZE==q.front)
return ERROR;
q.base[q.rear]=e;
q.rear=(q.rear+1)%MAXQSIZE;
return OK;
}
}
Status DeQueue(SqQueue &q, QElemType &e)
{
if(q.front==q.rear)
return ERROR;
e=q.base[q.front];
q.front=((q.front+1)%MAXQSIZE);
return OK;
}
QElemType GetHead(SqQueue q)
{
return q.base[q.front];
}
void PrintQueue(SqQueue q)
{
for(int i = q.front; i != q.rear; i = (i + 1) % MAXQSIZE) {
if(i != q.front)
cout << ' ';
cout << q.base[i];
}
cout << endl;
}
四.串
串的概念
串:由零个或多个任意字符组成的有限序列 子串:任意个连续字符组成的子序列,包含字串的串对应称为主串 空串:零个字符的串(与空格串不同
定义实现
顺序存储
typedef struct{
char ch[MAXLEN+1];
int length;
}SString;
链式存储
typedef struct{
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head *tail;
int curlen
}HString;
!?!串模式匹配算法思想与实现
BF算法
依次比较,最坏为O(m*n)
int Index_BF(SString S,SString T,int pos)
{
int i=pos,j=1;
while(i<=S.length&&j<=T.length)
{
if(S.ch[i]==T.ch[j]
{
i++;
j++;
}
else
{
i=i-j+1;
j=1;
}
if(j>=T.length)
return i-T.length;
else
return 0;
}
}
KMP算法
提速到O(m+n) nextval更快
void get_nextval(SString T,int &next[])
{
i=1;
next[1]=0;
j=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
i++;
j++;
if(T.ch[i]!=T.ch[j])
nextval[i]=j;
}
else
nextval[i]=nextval[j];
}
}
void get_next(SString T,int &next[])
{
i=1;
next[1]=0;
j=0;
while(i<T.length)
{
if(j==0||T.ch[i]==T.ch[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int Index_BF(SString S,SString T,int pos)
{
int i=pos,j=1;
while(i<=S.length&&j<=T.length)
{
if(S.ch[i]==T.ch[j]
{
i++;
j++;
}
else
{
j=next[j];
}
if(j>=T.length)
return i-T.length;
else
return 0;
五.二叉树
1. 二叉树的定义、性质
定义:
性质:
- 第i层至多有2^(i-1)个节点
- 深度为k的二叉树至多有2^k-1个节点
- 叶子节点(度为0)=其他节点(度都为2)+1
- n个节点的完全二叉树的深度为[log2n]+1(向下取整如7.1为7)
- 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从1开始编号
概念不好理解,但是看图就很容易理解
- 若i=1,则该节点为根,否则编号i/2的节点为其双亲节点
- 若2i>n,则该节点无左孩子,否则编号为2i的节点为其左孩子节点
- 若2i+1>n,则该节点无左孩子,否则编号为2i+1的节点为其左孩子节点
2. 对任何一棵二叉树能够写出它的先序、中序和后序序列
先序:根,左,右 中序:左,根,右 后续:左,右,根
3. 遍历二叉树的定义、方法(先序、中序和后序
定义实现
typedef string Element
typedef struct BiNode
{
Element data;
struct BiNode *lchild *rchild
}BiNode,*BiTree
操作
创建
void Creat(BiTree &T)
{
char ch[20];
if(!cin >> ch)
exit(0);
if(ch[0]=='#')
T=NULL;
else
{
T = new BiNode;
T->data=ch;
Creat(T->lchild);
Creat(T->rchild);
}
}
遍历
先序
void Order(BiTree T)
{
cout << T->data ;
Order(T->lchild);
Order(T->rchild);
}
层次遍历 原理:利用队列存放
void FoundTree(BiTree &t)
{
if(t==NULL)
return;
queue <BiTree> fk;
BiTNode *flag;
fk.push(t);
while(!fk.empty())
{
flag=fk.front();
fk.pop();
printf(" %c",flag->data);
if(flag->lchild)
fk.push(flag->lchild);
if(flag->rchild)
fk.push(flag->rchild);
}
}
4. 掌握二叉树求叶子节点、高度、总节点数、左右子树交换等算法。
叶子节点
int LeafNodeCount(BiTree T)
{
if(T==NULL)
return 0;
else if(T->lchild==NULL&&T->rchild==NULL)
return 1;
else
return LeafNodeCount(T->lchild)+LeafNodeCount(rchild);
}
高度
int Depth(BiTree T)
{
int m,n
if(T==NULL)
return 0;
else
m=Depth(T->lchild);
n=Depth(T->rchild);
if(m>n)
return m+1;
else
return n+1;
}
总结点数
int NodeCount(BiTree T)
{
if(T==NULL)
return 0;
else
return NodeCount(T->lchild)+NodeCount(rchild)+1;
}
左右子树交换
void SwapTree(BiTree &T)
{
BiTree S;
if(T==NULL)
return;
else
{
S=T->lchild;
T->lchild=T->rchild;
T->rchild=s;
}
SwapTree(T->lchild);
SwapTree(T->rchild);
}
}
六.哈夫曼树
掌握哈夫曼树的构造方法
会设计哈夫曼编码及带权路径长度的计算。
七.图
掌握图的基本概念
定义
图Graph=(V,E)
计算无向图的度和有向图的出入度
会写图或网的邻接矩阵;会画图的邻接表和逆邻接表;
重点掌握图的深度优先搜索和广度优先搜索,会根据邻接矩阵写出其深度优先搜索序列和广度优先搜索序列
普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法的算法思想,并利用算法解决实际问题。
八.查找
各种查找方法的算法思想
二叉排序树的定义与创建过程
掌握散列表处理冲突的方法(开放地址法、链地址法)以及求具体情况下的平均查找长度。
九.排序
各种内部排序方法的算法思想
重点掌握直接插入排序、冒泡排序、快速排序、简单选择排序和堆排序的算法思想与实现。
|