链表,栈,队列插入删除操作

     本文主要对常见的几种数据结构的插入删除操作进行整理和说明,具体的可视化程序可参考这里

1、链表

     1.1 单向链表

插入结点:在指针p所指的结点插入指针s所指的结点。

(1)s->next = p->next;

(2)p->next = s

删除节点:删除指针p所指的结点的后继节点。

p->next = p->next->next

具体问题可以参考《编程之美》中的从无头单链表中删除节点问题。

     1.2 双链式链表

插入结点:指针p所指的结点插入指针s所指的结点。

(1) s->prior = p->prior;

(2) p-> prior ->next = s;

(3) s->next = p;

(4) p->prior = s

删除节点:删除指针p所指的结点

(1)p->next->proir =p->prior;

(2)p->prior->next =p->next

2、栈

     2.1 顺序栈

     2.1.1  栈顶指针与栈中元素关系如下:

《链表,栈,队列插入删除操作》

      2.1.2 栈的数据结构

      《链表,栈,队列插入删除操作》

并做如下规定:

1. top=base 表示栈空 (int top :top=0 )

2. top – base>= stacksize 表示栈满;( top == stacksize )

3. 栈顶元素表示:*(top-1) (base[top-1] )

     2.1.3 基本操作

    构建空栈:

Status InitStack (SqStack &S)
{// 构造一个最大存储容量为 STACK_INIT_SIZE 的空栈S。
   S.base=(ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));
   if (!S.base) exit (OVERFLOW); //存储分配失败
   S.top = S.base;
   S.stacksize = STACK_INIT_SIZE;
   return OK;
}

      入栈:

Status Push (SqStack &S, SElemType e) {//TingH-stack
   //若栈的存储空间不满,则插入元素 e 为新的栈顶元素,     //并返回 TRUE;否则返回FALSE。 
if (S.top – S.base >= S.stacksize) //栈满,追加存储空间
   {S.base =(ElemType *) realloc ( S.base,  (S.stacksize + STACKINCREMENT) * sizeof (ElemType));
       if (!S.base) exit (OVERFLOW); //存储分配失败
       S.top = S.base + S.stacksize;
       S.stacksize += STACKINCREMENT;
   }
  *S.top++ = e;        //把e压入栈顶
    return OK;
}

      出栈:

Status Pop (SqStack &S, SElemType &e) {
     // 若栈不空,则删除S的栈顶元素,
     // 用e返回其值,并返回OK;
     // 否则返回ERROR
    if (S.top == S.base) return ERROR;//栈空
   e = *–S.top;   //此处可否使用 *S.top–
    return OK;
}

      获取栈顶元素:

bool GetTop (Stack S, ElemType &e){
// 若栈不空,则用 e 返回S的栈顶元素,
//并返回TRUE,否则返回FALSE
if (S.top == S.base)
return FALSE;
e = *(S.top-1); // 返回非空栈中栈顶元素
return TRUE;
}

     2.2 链式栈(略)

3、队列

      3.1 队列的顺序表示

    3.1.1 介绍

          为方便起见,我们约定:初始化建空队列时,令front=rear=0。每当插入新的队列尾元素时,尾指针增1;每当删除队列头元素时,头指针增1。

《链表,栈,队列插入删除操作》

但上述队列存在问题。设数组长度为M,则:

  1. 当front=0,rear=M时,再有元素入队发生溢出—真溢出;
  2. 当front!=0,rear=M时,再有元素入队发生溢出—假溢出.

解决方案如下:

  1. 队首固定,每次出队后剩余元素向下移动,但比较浪费时间;
  2. 循环队列。约定:front 指向队首元素,rear指向对尾元素的下一个位置

《链表,栈,队列插入删除操作》

为了区分上述循环队列中队空、队满,解决方法:少用一个元素空间,队空:front==rear,队满:(rear+1)%M==front。

      3.1.2循环队列的数据结构:

《链表,栈,队列插入删除操作》

       3.1.3基本操作:

             构造空队列:

Status InitQueue (SqQueue &Q) {
   // 构造一个空队列Q
   Q.base = (ElemType *) malloc  (MAXQSIZE *sizeof (ElemType));
    if (!Q.base) exit (OVERFLOW);     // 存储分配失败
    Q.front = Q.rear = 0;
     return OK;
}

          插入队尾元素:

Status EnQueue (SqQueue &Q, ElemType e) {   // 插入元素e为Q的新的队尾元素
    if ((Q.rear+1) % MAXQSIZE == Q.front)
        return ERROR;                  //①判满
    Q.base[Q.rear] = e;                 // ②插入队尾
   Q.rear = (Q.rear+1) % MAXQSIZE;    //③队尾指针后移
    return OK;
}

          删除队头元素:

Status DeQueue (SqQueue &Q, ElemType &e) {
// 若队列不空,则删除Q的队头元素,用e返回其值,
// 并返回OK;  否则返回ERROR
    if (Q.front == Q.rear)  return ERROR;
    e = Q.base[Q.front];
    Q.front = (Q.front+1) % MAXQSIZE;
    return OK;
}

      3.2 链式队列

          3.2.1 数据结构

《链表,栈,队列插入删除操作》

          3.2.2 基本操作

              构造空队列:             《链表,栈,队列插入删除操作》

               插入操作:(元素插入队尾)

《链表,栈,队列插入删除操作》

              删除操作:(删除队头元素)

《链表,栈,队列插入删除操作》

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/ttltry-air/archive/2012/08/15/2640511.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞