1 / 53

第 3 单元 线性数据结构(二)

第 3 单元 线性数据结构(二). 1.3 栈和队列 (P32~P46) 1.4 串和数组 (P47~P55). 1.3 栈和队列 一、栈的逻辑结构和运算. 1. 堆栈 (Stack) 概念 1) 只允许在同一端进行插入和删除操作的特殊线性表。 2) 允许进行插入和删除操作的一端称为栈顶,另一端为栈底; 3) 栈底固定,而栈顶浮动; 4) 特点:后进先出( LIFO )。 5) 空栈 : 元素个数为零的栈。. 2. 栈的基本运算. Setnull(Stack) 置栈为空;

wiley
Download Presentation

第 3 单元 线性数据结构(二)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第3单元 线性数据结构(二) • 1.3 栈和队列 (P32~P46) • 1.4 串和数组 (P47~P55)

  2. 1.3 栈和队列一、栈的逻辑结构和运算 • 1.堆栈(Stack)概念 • 1) 只允许在同一端进行插入和删除操作的特殊线性表。 • 2) 允许进行插入和删除操作的一端称为栈顶,另一端为栈底; • 3) 栈底固定,而栈顶浮动; • 4) 特点:后进先出(LIFO)。 • 5) 空栈:元素个数为零的栈。

  3. 2. 栈的基本运算 • Setnull(Stack) 置栈为空; • Empty(Stack) 判断栈是否为空; • Push(Stack,x) 进栈---在栈顶插入元素x • Pop(Stack) 出栈---删除栈顶元素; • Gettop(Stack) 取栈顶元素 • 顺序栈: 采用顺序存储结构的栈 • 链栈: 采用链式存储结构的栈

  4. 例1-10 • 有三个元素的进栈序列是1,2,3。写出可能的出栈序列。 出栈序列 操作序列 1 2 3 s x s x s x 1 3 2 s x s s x x 2 1 3 s s x x s x 2 3 1 s s x s x x 3 2 1 s s s x x x

  5. 3.与堆栈操作有关的术语 • 1) 栈顶指针TOP • 用来指出栈顶元素所在的位置 • 2) 栈空条件: top = -1 • 3) 栈满条件: top = MAXSIZE-1 • 4) 上溢 • 栈满后再进行入栈操作,产生上溢。 • 5) 下溢 • 栈已空,再执行出栈操作,产生下溢。

  6. 二、栈的存储结构之一:顺序栈 • 1) 采用顺序存储结构的栈 • 2) 实现: 使用一维数组 • 3) 栈顶位置随进栈和出栈而变化。 • 4) C语言描述: • #define MAXSIZE n • int stack[MAXSIZE]; • int top = -1; /*下标从0开始*/

  7. 栈操作举例 TOP a1 a2 …… an MAXSIZE-1 栈顶 栈底 1. A B C 2. (空栈) (A、B、C进栈) top=2 top=-1 A B C D E F 4. 3. A B top=MAXSIZE-1 (C出栈) top=1 (栈满)

  8. 算法1-8 进栈算法 • step1 判断栈满否, • 若满,显示溢出信息,停止执行 • 否则,执行step 2; • Step2 栈顶指针top上移(加1); • Step3 在top所指的位置插入元素x。

  9. 算法1-8 进栈算法程序 • push(int x) • { if(top == MAXSIZE -1) • { printf(“栈上溢!\n”); • exit (1); } • else • { top ++; /* 栈指针加 1 */ • stack[top]=x ; /* 元素 x进栈 */ • } • }

  10. 算法1-9 出栈算法 • step1 判断栈是否为空; • 若空,输出下溢信息,并停止执行; • 否则,执行step2; • step2 弹出(删除)栈顶元素; • step3 栈顶指针top下移(减1)。 • step4 返回栈顶元素

  11. 算法1-9 出栈算法程序 • pop( ) • { int x; • if( top = = -1) • { printf(“栈下溢\n”); exit(1);} • else • { x = stack [top];top - - ; } • return x ; • }

  12. 5) 两栈共享一个栈空间 • 两栈共享:两个栈底分别设在两端,栈顶指针top1和top2相对中间位置移动,栈间分界线不定。 • a. • b. • c. 空栈 top1 =0 top2=MAXSIZE-1 栈1、栈2均有元素 top1 top2 栈满 top1 top2

  13. 二、栈的存储结构之二:链栈 • 1. 顺序栈的问题 • 1) 最多实现2个栈的共享 • 2) 不能用于最大空间事先不知的情况 • 解决方法: 链栈

  14. 链栈存储结构 • 2. 链栈存储结构的C语言描述: • struct snode • { intdata; • struct snode *link; } ; • typedef struct snode SNODE ; • SNODE *top; • 链栈空:top = NULL • 链栈满: t = NULL /*t为申请的结点 • 申请结点失败

  15. 链栈示意图 ai top 栈顶 …... a3 a2 栈底 a1 NULL

  16. 算法1-10 进栈操作算法 • step1 申请一个链栈结点, • 若 t=NULL,则链满; • 否则,执行step2 ; • step2 在top所指结点之前插入新结点,并将top指向新申请的结点t。

  17. 算法1-10 进栈操作程序 • push(int x) • { SNODE *t; • t=(SNODE * )malloc(sizeof(SNODE)); • if (t = = NULL ) • { printf(“栈已满\n”); • exit(1); } • else • { t->data = x; t->link = top;top= t; } • }

  18. 算法1-11 出栈操作算法 • step1 若链栈空,输出栈溢出信息; • 否则,执行step 2。 • step2 删除top所指结点,并使top • 指向被删除结点的后继结点 • step3 释放被删除结点的存储空间 • step4 返回栈顶元素

  19. 算法1-11 出栈操作程序 • pop( ) • { SNODE *p; int x; • if ( top = = NULL ) • { printf(“栈下溢\n”); exit(1); } • else • { p=top; top=top->link; • x = p ->data ; free(p) ; } • return x; • }

  20. 三、队列 • 1. 队列概念 • 1) 只允许在表的一端进行删除操作,在表的另一端进行插入的特殊线性表。 • 2) 队尾(rear):进行插入操作的一端 • 3) 队头(front):进行删除操作的一端 • 4) 特点:先进先出(FIFO)。 入队 插入 出队 删除 a1 a2 … an front rear

  21. 2、队列的操作 • Setnull(Queue) 清空队列 • Empty(Queue) 判断队列是否为空 • Addqueue(Queue,x) 入队(插入) • Delqueue(Queue) 出队(删除) • Frontqueue(Queue) 取队头元素

  22. 四、队列的顺序存储 • 1. 定义空队列: 用一维数组 • #define MAXSIZE n • int queue[MAXSIZE]; • int front=-1, rear=-1; • front:队头指针; • rear:队尾指针; • 空队列:front = rear • 满队列:rear = MAXSIZE-1

  23. 2.入队出队操作 • 约定: • front: 总是指向队头元素的前一个位置; • rear: 总是指向队尾元素的位置 • 结果: 对任何元素,操作都一样 • 出队: 入队: • front = front + 1 ; rear=rear+1; • x = queue [front]; queue[rear]=x; a1 a2 … an front rear

  24. 入队时,rear在变 front rear A B C D E rear front 举例:顺序队列的入队、出队操作 • 1)空队列 • 2)A、B、C、D、E入队 • 3)A、B、C出队 出队时,front在变 D E rear front

  25. 4)F、G、H入队 • 5)D、E、F、G、H出队,出现假“溢出” D E F G H rear front rear front

  26. 3. 假溢出 • 假溢出 • 队列是空的情况下出现的溢出。 • 解决方法 • 1) 整个队列左移,费时 • 2) 队列的首尾相连--循环队列 • 目的 • 队列中真正没有空位置时,才产生溢出。

  27. 2.入队(队尾指针移动) rear=(rear+1)%MAXSIZE; 等价于: if (rear+1>=MAXSIZE) rear = 0; else rear=rear+1; 4、循环队列 • 1.出队(队头指针移动) • front=(front+1)%MAXSIZE; • 等价于: • if • (front+1>= MAXSIZE) • front = 0 ; • else • front=front+1;

  28. 循环队列队空、队满条件 3 2 1 • 约定: • 队头指针指示的 • 结点不用于存储 • 元素,只作标志 • 即保留一个节点 • 队空条件 • front = rear ; • 队满条件 • front = (rear+1) % MAXSIZE 空 0 front MAXSIZE -1 ... rear 2 1 a3 满 a2 0 a1 ... i ai MAXSIZE -1 ... rear i+1 front

  29. 算法1-12:循环队列入队算法 • step1 判别队列是否已满; • step2 队尾指针后移一个位置,将新结点元素值存入当前结点单元。 • 程序(略)

  30. 算法1-13 循环队列出队算法 • step1 判别队列是否为空;若空,则显示‘下溢’; • step2 队头指针后移一个位置。 • step3 返回队头元素 • 程序(略)

  31. 五.队列的链式存储结构 • 用带头结点的单链表作为队列的链式存储结构。 • C语言描述 • struct qnode • { int data ; • struct qnode * next;}; • typedef struct qnode QNODE ; • QNODE *front , *rear;

  32. 链队列的表示 • 链队列满: T = = NULL 没有存储空间 • 链队列空: front = =rear • 空队列: • 非空队列: front NULL rear front a1 a2 ... an NULL rear

  33. 算法1-14 链队列的入队算法 • step1 申请建立一个新结点T; • step2 判别T是否为NULL;若是,表示 • 队列已满; • step3 若非空,将T插入链中,修改rear • 指针。

  34. 链队列的入队操作 • addqueue(int x) • { QNODE *t; • t = (QNODE*)malloc(sizeof(QNODE)); • if ( t = = NULL) • { printf(”无可用空间\n”);exit(1);} • else • { rear -> next = t; rear = t; • t ->data = x; t ->next = NULL ; } • }

  35. an ^ 链队列的出队操作 • 两种情况: • 队列长度为1,修改头结点指针域和队尾指针。 • 队列长度大于1,只修改头结点指针域 front Queue anNULL rear T front Queue NULL rear ... front a1 a2 anNULL Queue rear ... a1 a2 ^ anNULL Queue front rear

  36. 栈的应用----例1: 递归过程 • 计算5的阶乘(5!=5×4×3×2×1) • { if ( n = = 1) return (1); • else return ( n * f(n-1)); • } f(1)=1 top f(2) 2*f(1) f(2)=2*f(1) f(3) 3*f(2) f(3)=3*f(2) f(4) 4*f(3) f(4)=4*f(3) f(5) 5*f(4) f(5)=5*f(4)

  37. 栈的应用----例2:程序的嵌套调用 • main sub1 sub2 sub3 top sub2 sub1 main

  38. 1.4 串和数组 • 一. 串及其运算 • 1. 串的概念 • 1) 定义: 特殊的线性表,每个数据元素仅由单个字符组成, 如: A="very good" • 2) 串的长度: 串中的字符个数 • 3) 空串:串长度为0 • 4) 空格串: 组成串的元素都是空格 • 5) 子串:串中任意个连续字符组成的序列 • 6) 两个串的相等:

  39. 2.串的基本操作 • LENGTH(S) 求串S的长度 • SUBSTR(S,start,len) 求S的子串 • CONCAT(S1,S2) • S2联接在S1末尾 • INDEX(S1,S2) • 确定S2在S1中的位置 • REPLACE(S1,S2,S3) • 用S3替换串S1中所有与串S2相等且不重叠的子串

  40. 二.串的存储结构 • 1. 顺序存储结构 • 用连续存储单元存储串的字符序列 • 使用字编址方式时,设1字4个字节,则: • (1)非紧缩存储:一个字的存储单元中只存放1个字符。 • 特点:存储密度低,浪费空间 • (2) 紧缩存储 一个单元中存放4个字符; • 特点:节省空间 • 访问时要花费分离时间

  41. 2. 链表存储结构 • (1) 结点由数据域和指针域组成 • 图1-38 • (2) 指针域通常两个字节 • 若数据域占一个字节: • 有效存储密度=1/3 • 若数据域占四个字节: • 有效存储密度=4/6=2/3

  42. 3.堆存储结构 • 堆结构:一种动态存储结构,定义一个很大的连续空间和相应的指针结构。 • 指针用来指示串在堆中的位置 • 例如,a=‘BEI’,b=‘ JING’, c=‘’,d=‘SHANGHAI’; 串名串长 起始地址 B E I J I N G S H a 3 1 A N G H A I b 5 4 c 0 9 d 8 9

  43. 三.数组 • 1、数组的定义 • 数组是有限个数组元素的集合 • 数组中所有元素有相同的数据类型 • 每个数组元素值可以用数组名和一组下标值唯一的确定;

  44. 2.数组元素之间的关系 • m行n列二维数组可以看作是m个或n个一维数组: • Amxn = ((a11a12…a1n),(a21a22…a2n),.. • (am1am2…amn)) • 或: a11 a12 a1n • a21 a22 a2n • Amxn = • am1 am2 amn ... ... ... ...

  45. 3.数组的操作 • 两种基本的操作: • 给定下标,存取相应的数组元素; • 给定下标,修改相应数组元素的值。

  46. 4.数组的顺序存储结构 • 无论几维数组,在计算机中都是按一维数组来存放。 • 二维数组存放通常采用两种方式: • 按行优先顺序 • 按列优先顺序

  47. 1) 按行优先顺序存储 • 按行优先将数组看作若干个行向量 • 数组中的每个元素由元素的两个下标表达式唯一的确定。 • 地址计算公式: • LOC(aij)=LOC(a11)+(i-1)*n+(j-1))*L • L: 每个元素所占的存储单元

  48. 2)按列优先顺序存储 • 将数组看作若干个列向量。 • 数组中的每个元素由元素的两个下标表达式唯一的确定。 • 地址计算公式: • LOC(aij)=LOC(a11)+((j-1)*m+(i-1))*L • L: 每个元素所占的存储单元。

  49. 5.矩阵的压缩存储 • 压缩的含义: • 相同值的多个元素占用一个存储单元; • 零元素不分配存储单元。 • (1)特殊矩阵的压缩存储 • 特殊矩阵:值相同的元素或非零元素分布有一定规律的矩阵 • 压缩:将二维数组的元素压缩到一维数组 • 关键:两个数组的下标之间建立映象关系

  50. 例: 对称矩阵的压缩存储 • 对称矩阵的元素满足: • aij = aji 1  i ,j  n • n*n 个元素压缩存放到n(n+1)/2 个单元的一维数组中。 • Aij在一维数组中的地址为: • i(i-1)/2+j 当ij • LOC(aij) = • j(j-1)/2+i 当i<j

More Related