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

ぐ巨炮叔叔 提交于 2019-12-17 18:37:32

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

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  栈顶指针与栈中元素关系如下:

image

      2.1.2 栈的数据结构

      image

并做如下规定:

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。

image

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

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

解决方案如下:

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

image

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

      3.1.2循环队列的数据结构:

image

       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 数据结构

image

          3.2.2 基本操作

              构造空队列:             image

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

image

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

image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!