2020USTC数据结构与算法课程复习

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))

大概就是个人学习的时候的想法吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值