zoukankan      html  css  js  c++  java
  • 数据结构与算法分析(三)

    数据结构与算法分析(三)

    这一次,我们说一说三种比较简单的数据结构,是一维的,分别是:

    1.表

    2.栈

    3.队列

    1.表

    对于表而言,当然可以用数组来实现,插入和删除的时候会带来巨大的开销,因此更多的时候,我们都是采用"链表(linked list)"这种形式.

    链表有很多变种,但是最基础的,基本功能是相似的,通常为了方便,链表的头(header)我们会放一个哑节点.

    我们用ADT的方式实现.

    Linked.h

    #ifndef LIST_H
    #define LIST_H
    
    #include <iostream>
    
    using namespace std;
    
    struct ListNode;
    typedef int ElementType;
    typedef struct ListNode *PtrToNode;
    typedef PtrToNode List;
    typedef PtrToNode Position;
    
    List CreateList();
    int IsEmpty(List L);
    int IsLast(Position P, List L);
    Position Find(ElementType X, List L);
    void Delete(ElementType X, List L);
    Position FindPrevious(ElementType X, List L);
    void Insert(ElementType X, List L, Position P);
    void DeleteList(List L);
    Position Header(List L);
    Position First(List L);
    void Print(List L);
    
    struct ListNode{
        ElementType Element;
        Position Next;
    };
    
    List CreateList(){
        Position P = new ListNode;
        P->Next = nullptr;
        return P;
    }
    
    int IsEmpty(List L){
        return L->Next == nullptr;
    }
    
    int IsLast(Position P, List L){
        return P->Next == nullptr;
    }
    
    Position Find(ElementType X, List L){
        Position P = L->Next;
        while(P != nullptr && P->Element != X){
            P = P->Next;
        }
        return P;
    }
    
    void Delete(ElementType X, List L){
        Position P = L->Next, tmpCell;
        P = FindPrevious(X, L);
        if(!IsLast(P, L)){
            tmpCell = P->Next;
            P->Next = tmpCell->Next;
            delete tmpCell;
        }
    }
    
    Position FindPrevious(ElementType X, List L){
        Position P = L;
        while(P->Next != nullptr && P->Next->Element != X){
            P = P->Next;
        }
        return P;
    }
    
    void Insert(ElementType X, List L, Position P){
        Position tmpCell = new ListNode;
        tmpCell->Element = X;
        tmpCell->Next = P->Next;
        P->Next = tmpCell;
    }
    
    void DeleteList(List L){
        Position P, tmpCell;
    
        P = L->Next;
        L->Next = nullptr;
        while(P != nullptr){
            tmpCell = P->Next;
            delete P;
            P = tmpCell;
        }
    }
    
    Position Header(List L){
        return L;
    }
    
    Position First(List L){
        return L->Next;
    }
    
    void Print(List L){
        Position P = L->Next;
        while(P != nullptr){
            cout << P->Element << "->";
            P = P->Next;
        }
        cout << "nullptr" << endl;;
    }
    
    #endif // LIST_H
    
    

    我们将所有的操作都放在Linked.h头文件里,如果在程序中想要引用,直接 #include就好.

    ADT可分为"数据集""操作集",很符合"面向对象"的思想.

    数据集:

    存放数据,以及下一个结点的地址,

    struct Node{
    ElementType Element;
    Position Next;
    };

    操作集:

    1.创建链表CreateList

    2.元素插入Insert

    3.元素删除Delete

    4.查找元素位置Find

    5.删除链表DeleteList

    特地增加了一个Print(List L)函数,方便测试时候使用.

    2.栈

    栈也是一种非常常见的数据结构,应用广泛.它的最大特点,在于它的后进先出特性,因此栈通常也被叫做'LIFO'表.栈的实现有两种,可以用链表,也可以用数组,两种方法我都会写,但我更倾向于选择链表这种实现方式,不仅节约空间,而且使用起来比较灵活.

    相较于普通的链表,栈无疑具有一些特殊的操作,主要是两个:

    进栈(Push)

    出栈(Pop)

    所谓Push就是把元素压入到栈的顶端,Pop操作就是把栈顶的元素取出来,并返回.

    链表实现

    Stack.h

    #ifndef STACK_H
    #define STACK_H
    
    #include <iostream>
    using namespace std;
    
    struct StackNode;
    typedef struct StackNode *PtrToNode;
    typedef PtrToNode Stack;
    typedef int ElementType;
    
    int IsEmpty(Stack S);
    Stack CreateStack();
    void MakeEmpty(Stack S);
    void Push(ElementType X, Stack S);
    ElementType Top(Stack S);
    ElementType Pop(Stack S);
    void DisposeStack(Stack S);
    void Print(Stack S);
    
    struct StackNode{
        ElementType Element;
        PtrToNode Next;
    };
    
    int IsEmpty(Stack S){
        return S->Next == nullptr;
    }
    
    Stack CreateStack(){
        Stack S = new StackNode;
        S->Next = nullptr;
        return S;
    }
    
    void MakeEmpty(Stack S){
        if(S == nullptr){
            return;
        }else{
            while(!IsEmpty(S)){
                Pop(S);
            }
        }
    }
    
    void Push(ElementType X, Stack S){
        PtrToNode tmpCell = new StackNode;
    
        tmpCell->Element = X;
        tmpCell->Next = S->Next;
        S->Next = tmpCell;
    }
    
    ElementType Top(Stack S){
        if(!IsEmpty(S)){
            return S->Next->Element;
        }
        return -1;
    }
    
    ElementType Pop(Stack S){
        if(!IsEmpty(S)){
            ElementType tmp;
            PtrToNode firstCell = S->Next;
            tmp = firstCell->Element;
            S->Next = firstCell->Next;
            delete firstCell;
            return tmp;
        }
        return -1;
    }
    
    void DisposeStack(Stack S){
        PtrToNode P = S->Next, tmp;
        S->Next = nullptr;
        while(P != nullptr){
            tmp = P->Next;
            delete P;
            P = tmp;
        }
    }
    
    void Print(Stack S){
        PtrToNode P = S->Next;
        while(P != nullptr){
            cout << P->Element << "->";
            P = P->Next;
        }
        cout << "nullptr" << endl;
    }
    #endif // STACK_H
    

    这里我依旧添加了一个Print()的函数,方便测试.

    数组实现

    StackArray.h

    #ifndef STACKARRAY_H
    #define STACKARRAY_H
    
    #include <iostream>
    
    using namespace std;
    
    typedef int ElementType;
    struct StackRecord;
    typedef struct StackRecord *Stack;
    
    int IsEmpty(Stack S);
    int IsFull(Stack S);
    Stack CreateStack(int MaxElements);
    void DisposeStack(Stack S);
    void MakeEmpty(Stack S);
    void Push(ElementType X, Stack S);
    ElementType Top(Stack S);
    ElementType Pop(Stack S);
    void Print(Stack S);
    
    struct StackRecord{
        int Capacity;
        int TopOfStack;
        ElementType *Array;
    };
    
    int IsEmpty(Stack S){
        return S->TopOfStack == -1;
    }
    
    int IsFull(Stack S){
        return S->TopOfStack == S->Capacity - 1;
    }
    
    Stack CreateStack(int MaxElements){
        Stack S = new StackRecord;
    
        S->Capacity = MaxElements;
        S->Array = new ElementType[MaxElements];
        MakeEmpty(S);
    
        return S;
    }
    
    void DisposeStack(Stack S){
        delete S->Array;
        delete S;
    }
    
    void MakeEmpty(Stack S){
        S->TopOfStack = -1;
    }
    
    void Push(ElementType X, Stack S){
        if(IsFull(S)){
            return;
        }else{
            S->Array[++S->TopOfStack] = X;
        }
    }
    
    ElementType Top(Stack S){
        if(IsEmpty(S)){
            return -1;
        }else{
            return S->Array[S->TopOfStack];
        }
    }
    
    ElementType Pop(Stack S){
        if(IsEmpty(S)){
            return -1;
        }else{
            return S->Array[S->TopOfStack--];
        }
    }
    
    void Print(Stack S){
        if(!IsEmpty(S)){
            for(int i = 0; i <= S->TopOfStack; ++i){
                cout << S->Array[i] << "->";
            }
        }
        cout << endl;
    }
    
    
    #endif // STACKARRAY_H
    
    

    3.队列

    与栈有所不同,队列是一种"先进先出"的数据结构,可以理解为排队:谁先到.就先为谁服务.队列会有一些跟高级的用法,这些后面才会涉及到,这里我们仅仅实现最基础的部分,同样可以分两种形式实现:数组和链表,具体应用中如何使用因人而异,如果数据量不是特别大的话,用数组实现也许会更加清楚直接一些.
    ADT这种形式对于数据结构的封装,无疑减轻了我们调用时的难度.

    QueueArray.h

    #ifndef QUEUEARRAY_H
    #define QUEUEARRAY_H
    
    #include <iostream>
    
    using namespace std;
    
    typedef int ElementType;
    struct QueueRecord;
    typedef struct QueueRecord *Queue;
    
    int IsEmpty(Queue Q);
    int IsFull(Queue Q);
    Queue CreateQueue(int MaxElements);
    void DisposeQueue(Queue Q);
    void MakeEmpty(Queue Q);
    ElementType Dequeue(Queue Q);
    ElementType Front(Queue Q);
    void Enqueue(ElementType X, Queue Q);
    static int Succ(int Value, Queue Q);
    void Print(Queue Q);
    
    struct QueueRecord{
        int Capacity;
        int Front;
        int Rear;
        int Size;
        ElementType *Array;
    };
    
    int IsEmpty(Queue Q){
        return Q->Size == 0;
    }
    
    int IsFull(Queue Q){
        return Q->Size == Q->Capacity;
    }
    
    Queue CreateQueue(int MaxElements){
        Queue Q = new QueueRecord;
    
        Q->Capacity = MaxElements;
        Q->Array = new ElementType[MaxElements];
        MakeEmpty(Q);
    
        return Q;
    }
    
    void MakeEmpty(Queue Q){
        Q->Size = 0;
        Q->Front = 0;
        Q->Rear = -1;
    }
    
    static int Succ(int Value, Queue Q){
        if(++Value == Q->Capacity){
            Value = 0;
        }
        return Value;
    }
    
    void Enqueue(ElementType X, Queue Q){
        if(IsFull(Q)){
            return;
        }else{
            Q->Rear = Succ(Q->Rear, Q);
            Q->Array[Q->Rear] = X;
            ++Q->Size;
        }
    }
    
    ElementType Dequeue(Queue Q){
        ElementType temp;
    
        if(IsEmpty(Q)){
            return -1;
        }else{
            temp = Q->Array[Q->Front];
            Q->Front = Succ(Q->Front, Q);
            --Q->Size;
        }
        return temp;
    }
    
    ElementType Front(Queue Q){
        if(IsEmpty(Q)){
            return -1;
        }else{
            return Q->Array[Q->Front];
        }
    }
    
    void DisposeQueue(Queue Q){
        delete Q->Array;
        delete Q;
    }
    
    void Print(Queue Q){
        int i, j = Q->Front;
        for(i = 0; i < Q->Size; ++i){
            cout << Q->Array[j] << "->";
            j = Succ(j, Q);
        }
        cout << endl;
    }
    
    #endif // QUEUEARRAY_H
    
    

    Queue.h

    #ifndef QUEUE_H
    #define QUEUE_H
    
    #include <iostream>
    
    using namespace std;
    
    typedef int ElementType;
    struct QueueNode;
    typedef struct QueueNode *PtrToNode;
    typedef PtrToNode Queue;
    typedef PtrToNode Position;
    
    int IsEmpty(Queue Q);
    Queue CreateQueue();
    void DisposeQueue(Queue Q);
    void MakeEmpty(Queue Q);
    ElementType Dequeue(Queue Q);
    ElementType Front(Queue Q);
    void Enqueue(ElementType X, Queue Q);
    void Print(Queue Q);
    
    struct QueueNode{
        ElementType Element;
        Position Next;
    };
    
    int IsEmpty(Queue Q){
        return Q->Next == nullptr;
    }
    
    Queue CreateQueue(){
        Queue Q = new QueueNode;
        Q->Next = nullptr;
        return Q;
    }
    
    void Enqueue(ElementType X, Queue Q){
        Position P = Q, tmpCell;
        while(P->Next != nullptr){
            P = P->Next;
        }
        tmpCell = new QueueNode;
        tmpCell->Element = X;
        tmpCell->Next = P->Next;
        P->Next = tmpCell;
    }
    
    ElementType Dequeue(Queue Q){
        if(IsEmpty(Q)){
            return -1;
        }else{
            Position P = Q->Next;
            ElementType temp;
            temp = P->Element;
            Q->Next = P->Next;
            delete P;
            return temp;
        }
    }
    
    ElementType Front(Queue Q){
        if(IsEmpty(Q)){
            return -1;
        }else{
            return Q->Next->Element;
        }
    }
    
    void DisposeQueue(Queue Q){
        Position P = Q->Next, tmpCell;
        Q->Next = nullptr;
        while(P != nullptr){
            tmpCell = P->Next;
            delete P;
            P = tmpCell;
        }
    }
    
    void Print(Queue Q){
        Position P = Q->Next;
        while(P != nullptr){
            cout << P->Element << "->";
            P = P->Next;
        }
        cout << endl;
    }
    
    #endif // QUEUE_H
    
    

    总结:三种数据结构:链表,栈,队列三种数据结构的实现均已完成.这三种数据结构或许在计算机科学中是最基本的三种数据机构了,应用广泛,栈可用来记录过程和函数调用,以及递归的实现,队列可用以处理计算机网络的访问分配,等等.下一节我们会接触到树这种更为复杂,也更为有意思的数据结构.

    却道,此心安处是吾乡
  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/lucifer25/p/7879877.html
Copyright © 2011-2022 走看看