博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构与算法分析(三)
阅读量:4969 次
发布时间:2019-06-12

本文共 9175 字,大约阅读时间需要 30 分钟。

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

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

1.表

2.栈

3.队列

1.表

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

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

我们用ADT的方式实现.

Linked.h

#ifndef LIST_H#define LIST_H#include 
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 
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 
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 
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 
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

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

转载于:https://www.cnblogs.com/lucifer25/p/7879877.html

你可能感兴趣的文章
Eclipse快捷键
查看>>
关于jar冲突的解决方向servlet-api
查看>>
洛谷P3369 【模板】普通平衡树(FHQ Treap)
查看>>
Android的Task和Activity相关
查看>>
PHP 安装
查看>>
CoreData基础
查看>>
cocos2d-html5 让图层阻挡下层触碰事件
查看>>
POJ 1850 Code 数位DP
查看>>
Ubuntu linux设置从当前目录下加载动态库so文件
查看>>
【Linux开发】CCS远程调试ARM,AM4378
查看>>
Scala的类和对象
查看>>
table相关的选择器 & children()与find()的区别 & 选择器eq(n)与nth-child(n)的差异
查看>>
Windows Azure Platform AppFabric
查看>>
springmvc常用注解标签详解
查看>>
Linux之ssh服务介绍
查看>>
Sql语句里的递归查询(转)
查看>>
[JAVA]《Java 核心技术》(一)
查看>>
libevent机制
查看>>
rabbit ip登录
查看>>
呼叫器
查看>>