Chapter 2 线性表和逆置问题

Chapter 2 线性表和逆置问题

- 2.1 线性表的基本概念和实现
(1)什么叫线性表:线性表是有相同特性数据元素的一个有限序列。
(2)线性表的逻辑特性:只有一个表头元素,只有一个表尾元素,表头元素无前驱,表尾元素无后继;其余元素只有一个直接前驱和直接后继。
(3)线性表的存储结构:顺序存储结构和链式存储结构,分别用于顺序表和链表。
①顺序表:元素按逻辑顺序,依次存储到从指定的存储位置开始的一块连续的存储空间中。
②链表:每个结点不仅包含所存元素的信息,还包含了元素间逻辑关系的信息(next or prior)
③两种存储结构的比较:
顺序表:
a.随机访问特性:顺序表只要知道存储的起始位置就可以知道任意一个结点的位置。
b.要求占用连续的存储空间,存储分配只能预先进行,操作过程中始终不变。
c.插入操作需要移动多个元素。
链表:
a.链表不支持随机访问:必须从头开始访问。所以结点的存储空间利用率比顺序表低。
b.存储空间的动态分配:不需要一次性的划分所有结点的空间给链表。
c.插入操作无需移动元素,而是修改插入位置旁边两个结点的指针域。
(4)5种形式的链表(关于头结点的问题和判断表空的条件,head为头结点)
①单链表:有一个next的指针域指向后继结点。
带头结点的单链表表空条件为:head->next=NULL
不带头结点的单链表表空条件为:head=NULL
②双链表:在单链表上添加一个prior的指针域,指向当前结点的前驱。
表空条件和单链表一样。
③循环单链表:把单链表的最后一个结点的指针域指向第一个结点。
表空条件和单链表一样。
④循环双链表:将双链表的最后一个结点的next指针指向第一个结点且将第一个结点的prior指针指向最后一结点。
带头结点的循环双链表:head->next==head;head->prior=head;或者两者的与和或语句。
不带头结点的单链表表空条件为:head=NULL
⑤静态链表:用一维数组表示。数组中的每一个结点有两个分量,一个是数据data,一个是指向下一个元素地址的指针(这个指针就是一个存下一个元素地址的int型的整型变量不是用来存储内存地址的变量型)
- 2.2 线性表的结构体定义和基本操作
(1)顺序表结构体定义:

# define maxSize 50
typedef struct {
   
   int data[maxSize];    //存放顺序表元素的数组,这里就体现了顺序表大小需要预定义
   int length;         //表示顺序表长度
}Sqlist;         //顺序表类型

(2)单链表结构体定义:

typedef struct LNode {
      //结构体名称
    int data;        //存放结点数据域
    struct LNode *next;   //指向后继结点的指针
}LNode;  //定义单链表结点类型

(3)双链表结构体定义

typedef struct DLNode {
   
    int data;
    struct DLNode *next;
    struct DLNode *prior;
} DLNode;

(4)定义一个结点:定义一个名字为A的指针指向这个结点

LNode *A = (LNode*)malloc(sizeof(LNode));

(5)顺序表的操作:(简单-略)
(6)单链表的操作:

  1. 插入操作:

例题2-1 A和B是两个带头结点的单链表,其中元素递增有序。设计一个算法,合并A和B为C,使C中元素值非递减有序。

void merge(LNode *A, LNode *B, LNode *&C) {
   
    LNode *p = A->next    //p为A的指针
    LNode *q = B->next    //q为B的指针
    LNode *r;            //r为C的指针
    C=(LNode *)malloc(sizeof(LNode));  //申请C的头结点空间,或者用C=A(用A的头结点做C的头结点)
    C->next=NULL;  
    free(B);
    free(A);
    r=C;    //r指向C的头结点
    while(p!=NULL && q!=NULL){
      //如果A和B都还有结点进行比较,选二者中较小的结点与C相连,从该循环跳出来至少必有一个线性表元素已经全部插入完毕。
        if(p->data <= q->data) {
    
            r->next=p;   //p指针在A表中所在的结点与C项链
            p=p->next;   //p指针后推
            r=r->next;    //r指针后推,指向C表新加入的结点中
        }
        else {
   
            r->next=q;
            q=q->next;
            r=r->next;
        }
    }
    r->next=NULL;
    if(p!=NULL) r->next=p;  //B中结点已经全加入C中,则直接把A中剩余结点加入C中
    if(q!=NULL) r->next=q;
}

例题2-2:假设有n个元素已经存储在数组a中,用尾插法和头插法建立链表C。(重点)
①尾插法:

void createlistR(LNode *&C, int A[], int n){
   
    LNode *s, *r; //s用来指向新申请的结点,r用来指向C的终端端点
    int i;
    C=(LNode *)malloc(sizeof(LNode));
    C->next=NULL;
    r=C;
    for(i=0;i<n;i++){
   
         s
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值