数据结构与算法(二)

数据结构与算法

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
第一章 绪论
第二章 线性表
第三章 树与二叉树
第四章 图
第五章 查找
第六章 排序



第二章 线性表

定义、抽象数据类型

  • 线性表:零个或多个数据元素的有限序列
  • ADT

线性表的实现

顺序存储
#define max 100
typedef ElemType int
struct LIST{
  ElemType elments[max];
  int last;
}
LIST L
单链表
struct celltype{
  ElemType data;
  celltype *next;
}
typedef celltype *LIST;
typedef celltype *position;

插入:

void Insert(ElemType x,position p,LIST &L)
{
  position q;
  q = new celltype;
  q ->data = x;
  q ->next = p->next;
  p->next = q;
}

如何对某一结点进行前插操作?1.找到 a i − 1 a_{i-1} ai1的位置,然后采用后插操作2.值交换
删除操作:

void Delete(position p,LIST &L)
{
  position q;
  if(p->next != NULL)
  {
    q = p->next;
    p->next = p->next->next;
    free(q)
  }
}

定位:

position Locate(ElemType x,LIST L)
{
  position p;
  p = L;
  while(p->next != NULL)
  {
    if (p->next->data == x)
      return p;
    else
      p = p->next;
  }
  return p;
}

提取:

ElemType Retrieve(position p,LIST L)
{
  return p->next-data;
}

寻找前驱:

position Previous(position p,LIST L)
{
  position q;
  if(p == L->next)
    cout<<"不存在前驱位置";
  else
  {
    q = L;
    while(q->next !=p)
      q = q->next;
    return q;
  }
}

寻找后继:

position Next(position p,LIST L)
{
  position q;
  if(p->next == NULL)
    cout<<"不存在后继位置";
  else
  {
    q = p->next;
    return q;
  }
}

创建空链表:

position MaleNull(LIST &L)
{
  L = new celltype;
  L->next = NULL;
  return L;
}

找尾结点:

position End(LIST L)
{
  position q;
  q = L;
  while(q->next != NULL)
    q = q->next;
  return q;
}

单链表的整表创建:头插法、尾插法

静态链表

把线性表的元素存放在数组的单元中(不一定按逻辑顺序连续存放),每个单元不仅存放元素本身,而且还要存放其后继元素所在的数组单元的下标(游标)
以 next== 1 作为其结束的标志
静态链表的插入和删除操作与动态链表的相同
有一个空闲表用来在插入新空间时申请空间

typedef struct{
  ElemType data;
  int next;
}spacestr;
spacestr SPACE[maxsize];//存储池
typedef int position,Cursor;

初始化:

void Initialize()
{
  int j;
  for (j = 0;j< maxsize-1,j++)
  {
    SPACE[j].next = j+1;
  }
  SPACE[j].next = -1;
  avail = 0;
}

可用空间的分配操作:

Cursor GetNode()
{
  Cursor p;
  if (SPACE[avail].next = -1)
    p = -1
  else
  {
    p = SPACE[avail].next;
    SPACE[avail].next = SPACE[p].next;
  }
  return p;
}

可用空间的回收操作

void FreeNode(Cursor q)
{
  SPACE[q.next]=SPACE[avail].next;
  SPACE[avail].next = q;
}

插入:

void Insert(ElemType x,position p,spacestr *SPACE)
{
  position q;
  q = GetNode();
  SPACE[q].data = x;
  SPACE[q].next = SPACE[p].next;
  SPACE[p].next = q;
}

删除:

void Delete(position p,spacestr *SPACE)
{
  position q;
  if(SPACE[p].next != -1)
  {
    q = SPACE[p].next;
    SPACE[p].next = SPACE[q].next;
    FreeNode(q);
  }
}
双向链表

是在单链表的每个结点中,再 设置一个指向其前驱结点的指针域。
结点有两个指针域,一个指向直接后继,另一个指向直接前驱

struct dcelltype{
  ElemType data;
  dcelltype *next,*prior;
}
typedef dcelltype *DLIST;
typedef dcelltype *position;

插入:

void Insert(ElemType x, position p,DLIST &L)
{
  s = new dcelltype;
  s->data = x;
  s->prior = p;
  s->next = p->next;
  p->next->prior =s;
  p->next = s;
}

删除:

void Delete(position p,DLIST &L)
{
  if(p->prior !=NULL)
    p->prior->next = p->next;
  if(p->next != NULL)
    p->next->prior = p->prior;
  delete p;
}
循环链表

将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表 (circular linked)
在表左端插入结点:

void LInsert(ElemType x,LIST &R)
{
  celltype *p;
  p = new celltype;
  p->data = x;
  if(R==NULL)
  {
    p->next = p;
    R = p;
  }
  else
  {
    p->next = R->next;
    R->next = p;
  }
}

在表右端插入结点:

void RInsert(ElemType x,LIST R)
{
  LInsert(x,R);
  R = R->next;
}

定义与操作

1、限定仅在表尾进行插入和删除操作的线性表
2、空栈:不含有任何数据元素的栈
3、栈顶和栈底:允许插入和删除的一端称为栈顶,另一端称为栈底
4、栈的操作:MakeNull(S),Top(S),Pop(S),Push(x,S),Empty(S)

顺序存储
struct STACK{
  int top;
  ElemType elements[maxlength];
} ;

置空:

void MakeNull(STACK &S)
{
  S.top = maxlength;
}

测试栈S是否为空:

boolean Empty(STACK S)
{
  if(S.top>maxlenth-1)
    return TRUE;
  else
    return FALSE;
}

返回栈S的栈顶元素:

ElemType Top(STACK S)
{
  if (Empty(S))
    return NULLES;
  else
    return S.elements[S.top];
}

弹出栈:

void Pop(STACK &S)
{
  if(Empty(S))
    cout<<"Stack is empty!"<< endl;
  else
    S.top = S.top+1;
}

压入栈:

void Push(ElemType x,STACK &S)
{
  if(S.top == 0)
    cout<<"stack is full!"<< endl;
  else
  {
    S.top = S.top-1;
    S.elements[S.top] = x;
  }
}
链式存储
struct node{
  ElemType val;
  node *next;
}
typedef node *STACK;

置空:

void MakeNull()
{
  STACK S;
  S = new node;
  S->next = NULL;
}

入栈:

void Push(ElemType x,STACK S)
{
  STACK stk;
  stk = new node;
  stk->val = elm;
  stk->next=S->next;
  S->next = stk;
}

出栈:

void Pop(STACK S)
{
  STACK stk;
  if(S->next)
  {
    stk=S->next;
    S->next = stk->next;
    delete stk;
  }
}

返回栈S的栈顶元素:

ElemType Top(STACK S)
{
  if(S->next)
    return S->next->val;
  else
    reutrn NULLES;
}

测试栈S是否为空:

boolean Empty(STACK S)
{
  if(S->next)
    return FALSE;
  else
    return TRUE;
}
栈的递归调用

递归过程在实现时,需要自己直接或间接调用自己,层层向下递归,返回次序正好相反

队列

定义

只允许在一端进行插入操作,而另一端进行删除操作的线性表。
操作:MakeNull(Q) Front(Q) EnQueue(x,Q) DeQueue(Q) Empty(Q)

顺序存储
struct queue{
  ElemType data[MaxSize];
  int front;
  int rear;
}

初始化:

void MakeNull(queue &Q){
  Q.front = MaxSize-1;
  Q.rear = MaxSize-1;
}

队列判空:

bool Empty(queue Q)
{
  if (Q.rear == Q.front)
    return TRUE;
  else
    return FALSE;
}

返回队首元素:

ElemType Front(queue Q)
{
  if (Empty(Q))
    return NULLESE;
  else
  {
    Q.front = (Q.front+1)%MaxSize;
    return Q.data[Q.front];
  }
}

入队:

void EnQueue(ElemType x,QUEUE &Q)
{
  if ((Q.rear+1)%MaxSize == Q.front)
    cout<< "队列满";
  else
  {
    Q.rear = (Q.rear+1)%MaxSize;
    Q.data[Q.rear] = x;
  }
}

出队:

void DeQueue(queue Q)
{
  if (Empty(Q))
    cout<< "空队列" << endl;
  else
    Q.front= (Q.front+1)%MaxSize;
}
链式存储
//结点
struct celltype{
  ElemType data;
  celltype *next;
};
//队列
struct queue{
  celltype *front;
  celltype *rear;
};

初始化与判空:

void MakeNull(queue &Q)
{
  Q.front = new celltype;
  Q.front->next = NULL;
  Q.rear = Q.front;
}
Boolean Empty(queue &Q)
{
  if (Q.rear == Q.front)
    return TURE;
  else
    return FLASE;
}

入队:

void EnQueue(ElemType x,queue &Q)
{
  q = new celltype;
  q->data = x;
  q->next = NULL;
  Q.rear->next = q;
  Q.rear =q;
}

出队:

void DeQueue(queue &Q)
{
  if (Q.rear == Q.front)
    cout<< "队空";
  p = Q.front->next;
  Q.front->next= p->next;
  if(p->next == NULL)
    Q.rear = Q.front;
  delete p;
}

返回队首元素:

ElemType Front(queue Q)
{
  if(Q.front->next)
    return Q.front->next->data;
}

顺序串与链串

模式匹配

朴素模式匹配算法(Brute-Force,BF)
从主串S的第一个字符开始和模式 T 的第一个字符进行比较,若相等,则继续比较两者的后续字符;否则,从主串S 的第二个字符开始和模式 T 的第一个字符进行比较。
重复上述过程,直到T 中的字符全部比较完毕,说明本趟匹配成功;或 S 中字符全部比较完,则说明匹配失败。

int StrMatch_BF(char *S, char *T, int pos = 0)
{
  /*S为主串 T 为模式,长度分别为了 lenS 和 lenT ;串采用顺序存储结构*/
  i = pos;
  j = 0;
  while(i<=lenS && j<= lenT){
    if(S[i] == T[j])
    {
      i++;
      j++;
    }
    else{
      i = i-j+1;
      j = 0 ;
    }
  }
  if(j>lenT)
    return i-lenT+1;
  else
    return -1;
}

KMP算法:

void Getnext(int next[],String t)
{
   int j=0,k=-1;
   next[0]=-1;
   while(j<t.length-1)
   {
      if(k == -1 || t[j] == t[k])
      {
         j++;k++;
         next[j] = k;
      }
      else 
        k = next[k];//此语句是这段代码最反人类的地方,如果你一下子就能看懂,那么请允许我称呼你一声大神!
   }
}

int KMP(String s,String t)
{
   int next[MaxSize],i=0;j=0;
   Getnext(t,next);
   while(i<s.length&&j<t.length)
   {
      if(j==-1 || s[i]==t[j])
      {
         i++;
         j++;
      }
      else j=next[j];               //j回退。。。
   }
   if(j>=t.length)
       return (i-t.length);         //匹配成功,返回子串的位置
   else
      return (-1);                  //没找到
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值