2020USTC数据结构与算法课程复习
#include<iostream>
#define Max_size 100
//DataStructure and Algorithm Review
//Linear Structure:
//Linear List
using namespace std;
typedef struct ListNode
{
int Data;
ListNode* next;
};//单链表结构,对应的操作:插入,删除,遍历(往下指,指到为空),循环链表,双链表,比较有意思的问题:求并集,交集
//链表中结点的插入
void ListInsert(ListNode *L,int elem,int direct){
ListNode *p,*q;
p=new ListNode;
p->Data=elem;
q=L;
while(!q->next){
if(q->Data==direct) break;
q=q->next;
}
if(q->next==NULL){q->next=p; p->next=NULL;}
else
{
p->next=q->next;
q->next=p;
}
}
//删除
void ListDelte(ListNode *L , int elem ,int res){
ListNode *p,*q;
p=q=L;
while(!p){
if(p->Data==elem){
q->next=p->next;
res=p->Data;
}
q=p;
p=p->next;
}
if(p==NULL){return;}
}
//Stack
typedef struct Stack//用循环数组表示栈
{
int* Date;
int top;
int stacksize;
};
typedef struct StackNode//用链表表示栈
{
int Data;
StackNode* next;
StackNode* top;
int stacksize;
};//栈的操作:Init(对使用数组表示十分重要),push,pop(栈最重要的两个操作),应用:主要是利用其LIFO的特性,比如求摆放箱子问题,数制转换,还有双向栈的表示
//使用数组时要时刻记得判断是否越界,如有则需Incerment操作
//栈的push
void Push(Stack &S,int elem){
//判断是否越界,若有则需用Incerment操作
S.Date[S.top]=elem;
S.top+=1;S.stacksize++;
}
//栈的pop
void Pop(Stack &S,int res){
if(S.top==-1){return ;}
S.top--;
res=S.Date[S.top];
S.stacksize--;
}
//Queue
typedef struct Queue//首先是用循环队列表示
{
int* Data;
int head;
int rear;
int queuesize;
};//如何用循环数组表示队列:rear=(rear+1)%n,head看需要动,若head==rear则空,若(rear+1)%n==head则满
//队列的操作
void EnQ(Queue Q,int elem){
if(Q.head==(Q.rear+1)%Q.queuesize){cerr << "It's full" <<endl; return;}
Q.Data[Q.rear]=elem;
Q.rear=(Q.rear+1)%Q.queuesize;
}
void DeQ(Queue Q ,int &res){
if(Q.rear==Q.head){return;}
res=Q.Data[Q.head];
Q.head=(Q.head+1)%Q.queuesize;
}
typedef struct QueueNode
{
int Data;
QueueNode* next;
QueueNode* head;
QueueNode* rear;
int queuesize;
};//队列的操作:Init(也是十分重要的),EnQ,DeQ(入队,出队最重要的两个),删除,插入,查找,遍历这一些操作同其余线性结构
//队列的应用:模拟排队,打印杨辉三角
//串
char Data[100];//就是字符串,操作还是那些东西,比较复杂的是KMP算法
//数组
//比较有意思的有:数组的一维化(自己找下标的规律),稀疏矩阵,三元组等
//树和二叉树
//二叉树的存储
typedef struct SqBiTree
{
int elem[Max_size];
int n;
};
//基于数组的顺序存储结构,只能用于完全二叉树的存储
typedef struct BTree
{
int data;
BTree *leftchild, *rightchild;
};
//二叉树的遍历
void PreOrder(BTree *root){
if(!root) return;
else
{
cout << root->data <<endl;
PreOrder(root->leftchild);
PreOrder(root->rightchild);
}
}//同理可写出中序,后序遍历,如果不用递归就只能用栈进行回溯
//二叉树的层序遍历
/*void LayerTravel(BTree *root){
InitQ(Q);
if(root) EnQ(Q,root);
while(!Empty(Q)){
DeQ(Q,p);
cout << p->Data;
if(p->left) EnQ(Q,p->left);
if(p->right) EnQ(Q,p->right);
}
}*/
//利用二叉树的遍历来做一些事情
//二叉树结点的个数
void CountNode(BTree *root,int count){
if(!root) return;
else
{
count++;
CountNode(root->leftchild,count);
CountNode(root->rightchild,count);
}
}
//输出二叉树从根节点到所有叶子节点的路径
/*void OutPath(BTree *root){
if(T)Push(S,root);
if(!root->left&&!root->right){
StackTraverse(S);
}
OutPath(root->left);
OutPath(root->right);
Pop(S,e);
}*/
//基于链表的存储(甚至可以加一个指向其父亲的指针)
//二叉树重要的操作遍历:先序,中序,后序
//HuffmannTree
typedef struct HuffmannTree
{
int weight;
int parent;
int left,right;
};//静态三叉数组存储哈夫曼树
//图
//邻接矩阵表示法
typedef struct Gragh
{
int Vex[100];//存放顶点的数组
int arcs[100][100];//邻接矩阵
int vexnum,arcnum;
int kind;//表明图的类型
};
//邻接表表示法
typedef struct Arcnode
{
int adjvex;//邻接点的位置下标
int weight;
Arcnode *next;
};
typedef struct Vexnode
{
int data;
Arcnode *first;
};
typedef struct Gragh2
{
Vexnode *elem;
int vexnum,arcnum;
int kind;
};//图最重要的两个操作DFS,BFS
//DFS,书上是利用两个函数,也可以用栈直接一个函数解决问题,但不论怎么样都要用visited数组
/*void DFS(Gragh G,int start){
int w;
visited[start]=1;
for(w=Firstarc(G,start);w!=-1;w=Nextarc(G,start,w)){
if(!visited[w])DFS(G,w);
}
}
*/
//WFS,最好的做法就是用队列
/*void WBFS(Gragh G,Queue *Q,int start){
visited[start]=1;
for(int i=Firstarc(G,start);i!=-1;i=Nextard(G,start,i){
if(!visited[i]) {visited[i]=1;EnQ(Q,i);}
}
while(!Empty(Q)){
DeQ(Q,start);
BFS(G,Q,start);
}
}
*/
//以上就是各种数据结构的基本定义和常用操作
//接下来是一些基本算法的实现
//查找算法:
//顺序查找
void SeqSearch(int A[],int key){
int size;
for(int i=0;i<size;i++){
if(key==A[i]){cout << i;return;}
}
}//ASL=(1+2+...+n)/n=(n+1)/2所以时间复杂度是O(n)
//二分查找
int BinSearch(int A[],int size,int key){//查找表有序(从小到大)
int mid=size/2,low=0,high=size-1;
while(low!=high){
if(key<A[mid]){
high=mid-1;
mid=(low+high)/2;
}
if(key>A[mid]){
low=mid+1;
mid=(low+high)/2;
}
if(key==A[mid])return mid;
}
}//ASL:当总查找数为n时,最大的查找次数j=log2(n+1),所以由ASL的计算式得,ASL=(n+1)log2(n+1)/n-1
//二叉查找树(一种动态的查找表)
BTree* BTreeSearch(BTree *root,int key){
BTree *p;
p=root;
while(p){
if(p->data<key){
p=p->leftchild;
}
if(p->data>key){
p=p->rightchild;
}
if(p->data==key) return p;
}
return NULL;
}//ASL=2*(n+1)log2(n+1)/n+C
//下面是排序:
//选择排序
void SelectSort(int A[],int size){
int min;
for(int i=0;i<size-1;i++){
min=0;
for(int j=size-1;j>i;j--){
if(A[j]<A[min])min=j;
}
swap(A[i],A[min]);
}
}//时间复杂度O(n^2),空间复杂度应该是O(1)
//起泡排序
void BubbleSort(int A[],int n){
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
if(A[j]>A[j+1])swap(A[j],A[j+1]);
}
}
}//O(n^2)
//插入排序
void InsertSort(int A[],int size){
int j;
for(int i=2;i<size;i++){
if(A[i]>A[i-1])continue;
A[0]=A[i];
for(j=i-1;A[0]<A[j];j++){
A[j+1]=A[j];
}
A[j+1]=A[0];
}
}//O(n^2)
//快排
void QuickSort(int A[],int low ,int high){
int privot=(low+high)/2;
swap(A[privot],A[high]);
int k=partition(A,low,high,A[high]);
if((k-low)>1)QuickSort(A,low,k-1);
if((high-k)>1)QuickSort(A,k+1,high);
}
int partition(int A[],int low,int high,int Elem_privot){
int l=low-1;
do{
while(A[++l]<Elem_privot);
while(high>low&&A[high]>Elem_privot);
swap(A[l],A[high]);
}while(l<high);
swap(A[l],A[high]);
return l;
}
//时间复杂度:最差O(n^2),最好O(log2(n))
大概就是个人学习的时候的想法吧