陈越《数据结构》第二章 线性结构

来源:互联网 发布:百度钱包贷款 知乎 编辑:程序博客网 时间:2024/06/09 15:08

2.1 线性表


2.1.1 基本知识


例1:一元多项式及其运算
f(x)=a0+a1x....+an1xn1+anxn
表示方法:
1. 顺序存储结构直接表示;
2. 顺序存储 结构;
(用结构数组表示:数组分量是由系数ai 、指数i组成的结构,对应一个非零项)
3. 链表结构存储非零项。
(链表中每个结点存储多项式中的一个 非零项,包括:系数和指数 两个数据域以及一个。)
这里写图片描述

启示

  1. 同一个问题可以有不同的表示(存储)方法;
  2. 有一类共性问题:有序线性序列的组织和管理。

线(定义时:1.数据对象集和操作集)
定义:由同类型 数据元素 构成的 有序序列 的 线性结构。

  1. 表中元素个数称为线性表的 长度
  2. 线性表没有元素时,称为 空表
  3. 表起始位置称 表头,表结束位置称 表尾

解析:



看看上面三个表达式分别是什么意思?

A) char *(*fun1)(char *p1,char *p2);B) char **fun2(char *p1,char *p2);C) char *fun3(char *p1,char *p2);

答:
C)这很容易,fun3是函数名,p1,p2是参数,其类型为char 型,函数的返回值为char 类型。

B) 也很简单,与C)表达式相比,唯一不同的就是函数的返回值类型为char**,是个二级指针。

A) fun1是函数名吗?回忆一下前面讲解数组指针时的情形。我们说数组指针这么定义或许更清晰:
int()[10]p;
再看看A)表达式与这里何其相似!明白了吧。这里fun1不是什么函数名,而是一个指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指针。同样,我们把这个表达式改写一下:
char()(charp1,charp2)fun1;
这样子是不是好看一些呢?只可惜编译器不这么想。
来源于.


structtypedefstruct
1 首先://注意在C和C++里不同
    在C中定义一个结构体类型要用typedef:
    typedef struct Student{
    int a;
    }Stu;
  于是在声明变量的时候就可:Stu stu1;(如果没有typedef就必须用struct Student stu1;来声明)
  这里的Stu实际上就是struct Student的别名。Stu==struct Student
  另外这里也可以不写Student(于是也不能struct Student stu1;了,必须是Stu stu1;)
    typedef struct{
    int a;
    }Stu;
    但在c++里很简单,直接
    struct Student{
    int a;
    };    
 于是就定义了结构体类型Student,声明变量时直接Student stu2;
 
2.其次:在c++中如果用typedef的话,又会造成区别:
    struct Student {
    int a;
    }stu1;//stu1是一个变量
    typedef struct Student2 {
    int a;
    }stu2;//stu2是一个结构体类型=struct Student
   使用时可以直接访问stu1.a
  但是stu2则必须先 stu2 s2;
  然后 s2.a=10;

3. 给出一个实例
typedef struct tagMyStruct{
     int iNum;
     long lLength;
    } MyStruct;
 C
    (1) struct tagMyStruct 变量名;
    (tagMyStruct称为”tag”,即”标签”,实际上是一个临时名字,不论是否有typedefstruct 关键字和tagMyStruct一起,构成了这个结构类型,这个结构都存在。)
    (2) MyStruct 变量名
    c++
    (1) struct tagMyStruct 变量名
    (2) MyStruct 变量名
    (3) tagMyStruct 变量名
来源于。



Qus:
typedef struct{
ElementType Data[MAXSIZE];
int Last;
} List;
List L, *PtrL;
然后是初始化的
1. 初始化(建立空的顺序表)
List *MakeEmpty( )
{ List *PtrL;
PtrL = (List *)malloc( sizeof(List) );
PtrL->Last = -1;
returnPtrL;
}

初始化空的列表直接给他List L, *PtrL;把指针赋过去不就好了吗,为什么还要搞出MakeEmpty( )啊?

Ans:
MakeEmpty( )完成的工作:
1、动态申请了顺序表的空间;
2、设置表指针为-1;
3、返回了表的指针;
你的操作 List L, *PtrL;
PtrL = &L;
L.Last = -1;
来源于。


2.1.2 顺序存储


  1. 定义:利用数组的 连续存储空间顺序存放 线性表的各元素。
    这里写图片描述

各种操作的时间性能:
1. 查找O(k);
2. 插入O(n);
这里写图片描述
3. 删除O(n);
这里写图片描述

2.1.3 链式存储


定义:
这里写图片描述
结构的定义:
引用块内容

基本操作:
1. 求表长,时间性能为 O(n)。
2. 查找,按序号查找: FindKth 和 按值查找: Find,时间性能为 O(n)。
3. 插入,时间性能为 O(n)。
这里写图片描述
4. 删除,时间性能为 O(n)。
这里写图片描述


2.1.4 广义表和多重链表


2.1.4.1 广义表

这里写图片描述


2.1.4.2 多重链表

这里写图片描述

例子:表示稀疏矩阵
这里写图片描述


2.2 堆栈


2.2.1堆栈定义和堆栈的抽象数据类型

例1:中缀表达式a+bcd/e,请问前缀表达式和后缀表达式是什么?

  • 前缀表达式: +abcd/e;
  • 后缀表达式:abc+de/.
    如果用后缀表达式来进行计算,实质就是堆栈的应用!

堆栈定义:
具有一定 操作约束 的线 只在( 栈顶 ,Top )做
这里写图片描述

例2:如果 三 个字符 按ABC 顺序压入堆栈:
ABC 的所有排列都可能是出栈的序列 吗 ?
• 可以产生CAB这样的序列吗?
这里写图片描述


2.2.2 顺序存储


例3:请用一个数组实现两个堆栈,要求最大地利用数组空间,使数组只要有空间入栈操作就可以成功。

解析
一种比较聪明的方法是使这两个栈分别从数组的 两头开始向中间生长;当两个栈的 栈顶指针相遇 时,表示两个栈都满了。
这里写图片描述


2.2.3 堆栈的链式存储及应用


链式存储定义:
栈的链式存储结构 实际上就是 一个 单链表,叫做 链栈 。插入和删除操作只能在链栈的栈顶进行。Top

:栈顶放在链表的表头,放在尾部不行!

应用::中缀表达式求值。
基本策略:将中缀表达式转换为后缀表达式,然后求值,如何将中缀表达式转换为后缀?

步骤:
这里写图片描述

堆栈的其他应用:
1. 函数调用及递归实现
2. 深度优先搜索
3. 回溯算法
….


2.3 队列


2.3.1 定义及顺序存储


1.定义:FIFO
这里写图片描述

这里写图片描述

这里写图片描述

2.队列的顺序存储
例1:队列 的顺序存储结构通常由一个 一维数组 和一个记录 队列头 元素位置的变量front 以及 一个记录 队列尾 元素位置的变量rear 组成。

为了抑制现象,我们用循环队列进行模拟,但是会出现“空”和“满”无法判断的情况,我们运用:
1. 另设变量;Size(计算队列内元素个数)和tag(标记队列中是否有元素);
2. 少用一个空间元素。
:通常用求余方法进行求解(%)。


2.3.2队列的链式存储

定义:
队列 的 链式 存储结构 也可以用 一个 单链表 实现。插入和删除操作分别在链表的两头进行;队列指针frontrear 应该分别指向 链表的 哪一 头 ?

答:
front单链表表头,rear单链表表尾。

这里写图片描述

例1:如何用两个栈模拟实现一个队列? 如果这两个堆栈的容量分别是m和n(m>n),你的方法能保证队列的最大容量是多少?(这里讨论的是顺序栈,如果是链式栈的话完全没有必要考虑空间)
答:
:用一个栈作为存储空间,另一个栈作为输出缓冲区,入队时把元素按顺序压入两栈模拟的队列,出队时按入队的顺序出栈即可。
:两个栈所模拟的队列的最大容量为2n+1。


2.4 应用实例及小白专场


多项式的加法和乘法:
这里写图片描述

//author: Paul_Huang//Data: 15/6/2017#include<iostream>#include <stdlib.h>#include<stdio.h>typedef struct PolyNode *Polynomial;struct PolyNode{    int coef;   //系数    int expon;  //指数    struct PolyNode *link;  //指向下一个节点的指针};Polynomial P1,P2;Polynomial ReadPoly();void Attach(int coeff, int expon, Polynomial *pRear);Polynomial PolyAdd(Polynomial P1, Polynomial P2);Polynomial PolyMulti(Polynomial P1,Polynomial P2);void PrintPoly(Polynomial P);   //输出多项式int main(){    Polynomial P1,P2,PP,PS;    P1 = ReadPoly();        P2 = ReadPoly();    PP = PolyMulti(P1,P2);    PrintPoly(PP);    PS = PolyAdd(P1,P2);    PrintPoly(PS);    system("pause");//暂停往下执行 按下任意键继续    return 0;}Polynomial ReadPoly(){    int i;    int coeff,expon;    Polynomial first,rear,temp;    /*input count number*/    scanf("%d",&i);    first = (Polynomial) malloc(sizeof(struct PolyNode));    first->link = NULL;    rear = first;    /*read the Poly*/    while(i--)    {        scanf("%d %d",&coeff,&expon);        Attach(coeff,expon,&rear);    }    temp = first; first = first->link; free(temp);    return first;}void Attach(int coeff, int expon, Polynomial *pRear){    Polynomial P;    P = (Polynomial) malloc(sizeof(struct PolyNode));    P->coef = coeff;    P->expon = expon;    P->link = NULL;    /*将P指针指向新节点*/    (*pRear)->link = P;    *pRear = P;}Polynomial PolyAdd(Polynomial P1, Polynomial P2){    Polynomial front,rear,temp;    int sum;    front = (Polynomial) malloc(sizeof(struct PolyNode));   //链表附加头结点    front->link = NULL;    rear = front;    while(P1&&P2)    {        if(P1->expon == P2->expon)        {            sum = P1->coef + P2->coef;            if(sum) Attach(sum,P1->expon,&rear);            P1 = P1->link;            P2 = P2->link;        }        else if(P1->expon > P2->expon)        {            Attach(P1->coef,P1->expon,&rear);            P1 = P1->link;        }        else        {            Attach(P2->coef,P2->expon,&rear);            P2 = P2->link;        }    }    /*  将未处理完的另一个多项式的所有节点依次复制到结果多项式中去  */    for(;P1;P1=P1->link)    Attach(P1->coef,P1->expon,&rear);    for(;P2;P2=P2->link)    Attach(P2->coef,P2->expon,&rear);    temp = front;front = front->link; free(temp);    return front;}Polynomial PolyMulti(Polynomial P1,Polynomial P2){    Polynomial front,rear,temp,sP2;    int coeff = 0,expon = 0;    if(!P1||!P2)    return NULL;        //先对其进行验证;    front = (Polynomial) malloc(sizeof(struct PolyNode));    front->link = NULL;    rear = front;    sP2 = P2;    /*先准备第一列。对其进行对比*/    while(P2)    {        Attach(P1->coef * P2->coef , P1->expon + P2->expon , &rear);        P2 = P2->link;    }    /*以下加上去的项是由上面的项进行比较*/    P1 = P1->link;    while(P1)    {        P2 = sP2;           //恢复P2初始位置        rear = front;       //从表头开始扫描结果多项式链表        while(P2)        {            coeff = P1->coef * P2->coef;            expon = P1->expon + P2->expon;            while(rear->link && rear->link->expon > expon)  //结果多项式链表中的数据项指数较大            {                rear = rear->link;            }            if(rear->link && (rear->link->expon ==expon))   //两数据项指数相等            {                if(rear->link->coef + coeff)        //系数和非0                {                    rear->link->coef +=coeff;                }                else                //系数和为0,需要在结果多项式链表中删除次表项                {                    temp = rear->link;                    rear->link = temp->link;                    free(temp);                }            }            else                 //结果多项式链表中的数据项指数较小            {                temp = (Polynomial) malloc(sizeof(struct PolyNode));                temp->coef = coeff;                temp->expon = expon;                temp->link = rear->link;    //把新表项插入到结果多项式链表中                rear->link = temp;                rear = rear->link;            }            P2 = P2->link;        }        P1 = P1->link;    }    temp = front;front = front->link;free(temp);    return front;}void PrintPoly(Polynomial P)    //输出多项式{    int flag=0;        //输出序号,用来辅助调整输出格式    if(!P){ printf("0 0\n"); return;}  //当多项式链表为空    while(P)    {        if(!flag)    flag=1;  //第一次输出,没有前置空格        else   printf(" ");   //输出前置空格        printf("%d %d",P->coef,P->expon);        P = P->link;    }    printf("\n");}

这里写图片描述

#include <stdio.h>#include <stdlib.h>typedef int ElementType;typedef struct Node *PtrToNode;struct Node {    ElementType Data;    PtrToNode   Next;};typedef PtrToNode List;List Read(); /* 细节在此不表 */void Print( List L ); /* 细节在此不表;空链表将输出NULL */List Merge( List L1, List L2 );int main(){    List L1, L2, L;    L1 = Read();    L2 = Read();    L = Merge(L1, L2);    Print(L);    Print(L1);    Print(L2);    system("pause");//暂停往下执行 按下任意键继续    return 0;}List Read(){    int i , coeff;    PtrToNode first , rear , temp;    /*input count number*/    scanf("%d",&i);    if(i == 0)       return NULL;    /*initialization*/    first = (PtrToNode) malloc(sizeof(struct Node));    first->Next = NULL;    rear = first;    /*get number*/    while(i--)    {        temp = (PtrToNode) malloc(sizeof(struct Node));        scanf("%d",&coeff);        temp->Data = coeff;        rear->Next = temp;        rear = temp;        /*free(temp);*/    }    temp = first; first = first->Next; free(temp);    rear->Next = NULL;    return first;}void Print(List L){    int flag = 0;    if(!L)    {        printf("NULL\n");        return;    }    while(L)    {        printf("%d ",L->Data);        L = L->Next;    }    printf("\n");}List Merge( List L1, List L2 ){    PtrToNode front,rear,temp;    //int coeff;    /*初始化链表*/    front = (PtrToNode) malloc(sizeof(struct Node));    front->Next = NULL;    rear = front;    while(L1&&L2)    {        if(L1->Data <= L2->Data)        {            temp = (PtrToNode) malloc(sizeof(struct Node));            temp->Data = L1->Data;            rear->Next = temp;            rear = temp;            L1 = L1->Next;              }        else        {            temp = (PtrToNode) malloc(sizeof(struct Node));            temp->Data = L2->Data;            rear->Next = temp;            rear = temp;            L2 = L2->Next;        }    }     while(L1)     {          temp = L1;          rear->Next = temp;        rear = temp;         L1=L1->Next;      }      while(L2)    {          temp = L2;          rear->Next = temp;        rear = temp;       L2 = L2->Next;       }    temp = front; front = front->Next;free(temp);    L1->Next=NULL;      L2->Next=NULL;          return front;}
原创粉丝点击