本文主要对常见的几种数据结构的插入删除操作进行整理和说明,具体的可视化程序可参考这里。
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,则:
- 当front=0,rear=M时,再有元素入队发生溢出—真溢出;
- 当front!=0,rear=M时,再有元素入队发生溢出—假溢出.
解决方案如下:
- 队首固定,每次出队后剩余元素向下移动,但比较浪费时间;
- 循环队列。约定: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