线性表定义--线性表的顺序存储结构+链式存储结构+循环链表+双向链表_xavier679的博客-程序员秘密

技术标签: 数据结构  

线性表
一、线性表定义:
1、线性表的定义

通过一个例子来体验什么是线性表的定义:小朋友出游排队。谁在谁的前面,谁在谁的后面,保证不会有人丢失。
定义:线性表(List):零个或多个数据元素的有限序列。

注意:
1)线性表是一个序列。也就是说,线性表的元素之间是有序的。若元素存在多个,对于其中一个元素来说,它前面的元素叫前驱,后面的元素叫后继。第一个元素无前驱,最后一个元素无后继,中间的元素只有一个前驱,一个后继。
2)线性表是有限的。事实上,在计算机科学领域,我们只研究有限的序列,因为计算机的处理对象都是有限的。而对于那些无限的序列,只在数学中讨论。

线性表的元素个数n(n>=0)定义为线性表的长度,当n=0时,称为空表。
练习:说明以下数据集是否是线性表
1、一年中的十二星座(古巴比伦人发明,使用60进制,空中花园,时间也是他们发明的,被波斯灭国,对数学的贡献有着极其重要地位)
2、一个公司的组织架构(非皮包公司)
3、一个班级间的同学关系
4、班级同学的点名册
5、播放器的播放列表
6、linux的文件系统
答案:
1、4、5是,2、3、6不是
===============================================================================
二、线性表的顺序存储结构
1、定义存储结构
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
在C语言中,我们可以使用一维数组来实现顺序表的存储结构。即把表的第一个元素数据存放到数组下标为0的位置中,接着把线性表相邻的元素存储到数组中的相邻位置。
线性表的顺序存储结构代码:
#define MAXSIZE 20
typedef int data_t; //编程的普适性、方便移植,脚本没有变量类型
typedef struct
{
data_t data[MAXSIZE];
int length;
}SqList;
这里要区分线性表长度与数组长度的区别。数组长度是存放线性表的存储空间长度,在编译后这个存储空间就不变了。而线性表长度指的是线性表中的数据元素个数,随着线性表的操作,这个数据是变化的。在任意时刻,线性表长度应该小于等于数组长度。
对于顺序表来说,逻辑位置上相邻的两个元素,其在存储位置上也是相邻的。例如a[i]和a[i+1],二者在逻辑结构上是前后关系,在存储结构上也是前后关系。
===============================================================================
2、顺序表的操作:
设有顺序表sq,对顺序表的操作有:
⒈建立一个空顺序表(CreateEmptySqList)
⒉清空一个顺序表(ClearSqList)
⒊判断顺序表是否为空(ListEmpty)
⒋求表长(SqListLength)
⒌获得表中第i个位置的元素(GetElem)
⒍确定某元素在顺序表中的位置(LocateElem)
⒎插入一个新的元素(InsertSqList)
⒏删除第i个位置的元素(DeleteSqList)
⒐遍历该顺序表(PrintSqList)
===============================================================================
3、插入与删除
有关于顺序表的相关操作,一些操作是十分简单的。例如:求表长,查询第i个位置元素,置空,遍历等。这里不详细讲解。对于顺序表来说,重点要掌握它的插入与删除操作。
1)获得元素
对于线性表的顺序存储结构来说,获取第i个位置的元素是非常简单的。
//代码见附录
2)插入操作
举个例子:一队人在排队买票,这时来了一个插队的,他插入到的队伍的第i个位置,那么在他之后的人都要向后挪一步。
在这个例子中我们已经说明了线性表的顺序存储结构在插入数据时的实现过程。
插入算法思路:
⒈如果插入位置不合理,返回异常
⒉如果线性表长度大于等于数组长度,则返回异常或增加容量
⒊从最后一个位置开始向前遍历到第i个位置,分别将它们都向后移动一个位置
⒋将要插入元素填入位置i处
⒌表长加1
//代码见附录
3)删除操作
接着刚才的例子:此时后边排队的人意见很大,这时他冲出了队伍,消失在人群中。于是排队的人群又想蠕虫一样向前移动了一步,队伍又恢复了平静。
这就是线性表的顺序存储结构删除元素的过程。
删除算法思路:
⒈如果删除位置不合理,返回异常
⒉取出删除元素
⒊从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置
⒋表长减1
//代码见附录
===============================================================================
4、线性表顺序存储结构的优缺点
优点:
⒈无需为表示表中元素之间的逻辑关系而额外增加额外的存储空间
⒉可以快速地存取表中任意位置的元素
缺点:
⒈插入和删除操作需要移动大量元素
⒉当线性表长度变化较大时,难以确定存储空间的容量
⒊可能造成存储空间“碎片”
===============================================================================
下下下下下下下下下下下下下下下下下下半段
===============================================================================
一、线性表的链式存储结构--------- 空表,头插法等有头节点的话很方便,
前面所讲的线性表的顺序存储结构是有缺点的,最大的缺点就是插入和删除时需要移动大量的元素,这显然就需要耗费大量时间。
仔细考虑一下产生该问题的原因,在于相邻元素的存储位置也具有邻居关系,它们在内存中是紧挨着的,没有空隙,自然也没有空位进行介入,而删除后留下的空隙自然也需要弥补。
为了解决上述问题,我们打破常规,不再让相邻元素在内存中紧挨着,而是上一个元素留存下一个元素的“线索”,这样我们找到第一个元素时,根据“线索”自然而然就找到下一个元素的位置;依次类推,通过遍历的方法每一个元素的位置都可以通过遍历找到。(达芬奇密码、国家宝藏)
===============================================================================
1、线性表的链式存储定义
定义:节点(或译为“结点”)(Node):为了表示每个数据元素ai与其后续数据元素ai+1之间的逻辑关系,对数据ai来说,除了存储本身的数据信息之外,还需要存储一个指示其直接后继信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称作指针或链。这两部分信息组成数据元素ai的存储映像,称为节点(Node)。
定义:单链表:n个节点(ai的存储映像)链接成一个链表,即为线性表的链式存储结构。因为此链表的每个节点中只包含一个指针域,所以叫单链表。
定义:头指针:我们把链表中第一个节点的存储位置叫做头指针,整个单链表的存储就必须从头指针开始进行。
但是,单纯使用头指针无法区分一个单链表是否为空 还是 一个单链表不存在。因为二者从头指针的角度来说,都是指针为空,而单链表为空和单链表不存在是两种完全不同的概念。
为了解决这个问题,我们引入头结点head的概念。头结点即单链表的第一个节点,该节点不存储任何有效数据,实际链表的起点是头结点的后继节点。
当头结点的后继节点为空,即
head->next==NULL
时,此时我们判定该链表为空链表。而当头结点head不存在时,此时我们判定该单链表不存在。
===============================================================================
2、线性表的链式存储结构代码描述
单链表的存储结构的C语言描述:
typedef struct Node
{
data_t data;
struct Node *next;
}Node;
typedef struct Node *LinkList;
由代码我们可以看出,节点是由存放数据元素的数据域和存放后继节点的指针域组成的。假设指针p是指向第i个元素ai的指针,则p->data表示ai的数据域,p->next表示ai的指针域。p->next指向下一个元素,即ai+1,也就是说,p->data=ai,p->next->data=ai+1。
===============================================================================
3、链表的操作:
设有线性表Head,对链表的操作有:
⒈建立一个空链表(CreateEmptyLinkList)
⒉清空一个链表(ClearLinkList)
⒊判断线性表是否为空(LinkListEmpty)
⒋整表创建(InsertTail、InsertHead)
⒌获得表中第i个位置的元素(GetElem)
⒍插入一个新的元素(InsertLinkList)
⒎删除第i个位置的元素(DeleteLinkList)
⒏遍历该线性表(PrintLinkList)
⒐倒置一个链表(LinkListReverse面试经常问到)

1)单链表的整表创建
在顺序表中,顺序表的创建其实就是一个数组的初始化过程。而单链表和顺序表的存储结构不同,它不能像顺序表一样整体集中地操作数据,而且单链表是一种动态结构。所以创建单链表的过程实际上是将一个“空表”动态依次建立各元素节点并逐步插入到链表中的过程。
单链表的整表创建的算法思路(头插法):
⒈声明指针p和计数器i
⒉初始化一个空链表头结点head
⒊让head的结点指针指向NULL,即建立一个带头结点的空单链表
⒋循环以下过程:
⒋⒈通过指针p生成新节点
⒋⒉新节点获得数据,即p->data=数据
⒋⒊将p插入到头结点与前一新节点之间
//代码见附录
以上代码里,我们让新生成的节点始终处在第一个位置,我们把这种方法称为“头插法”。
实际上,按照日常生活中“先来后到”的思想,新生成的节点应当插入到当前链表的尾部。若采用这种方法创建单链表,我们称为“尾插法”。
尾插法的算法思路基本等同于头插法,只需将上文的头插法的算法
⒋⒊将p插入到头结点与前一新节点之间
改为:
⒋⒊将p插入到当前链表的尾节点之后
即可。
//代码见附录
注意代码中L与r的关系,L是指向整个单链表,而r是指向当前链表的尾节点。L不会随着循环变换位置,而r会随着循环实时变换位置。

2)单链表的整表删除
当我们不打算使用一个链表时,我们应当对其进行销毁,也就是在内存中释放这个链表,以便留出空间供其他程序使用。
单链表的整表删除的算法思路:
⒈声明指针p和q;
⒉将链表的第一个节点赋值给p
⒊循环以下过程:
⒊⒈将p的下一个节点赋值给q
⒊⒉释放p
⒊⒊将q赋值给p
//代码见附录
注意代码中指针q的作用,q的作用是引导指针p,若无指针q的话,在执行free(p)语句之后,指针p就无法找到其下一个节点p->next的位置了,因为该节点的指针域已经随节点一并释放了。

3)单链表的读取
在线性表的顺序存储结构中,我们要通过任意位置读取元素的值是十分方便容易的,但在单链表中,对于第i个元素具体在哪无法一开始就得知,必须从头指针开始寻找。因此对于单链表的读取第i个元素的操作在算法上相对要麻烦很多。
获得单链表第i个元素的算法:
⒈定义一个指针指向链表的第一个节点。初始化循环变量j
⒉当j<i时,不断让指针p向后移动
⒊若到链表结尾p为空,则说明第i个节点不存在,返回错误
⒋当p移动到i位置成功时,返回节点p的数据
//代码见附录
因为该链表的时间复杂度取决于位置i,因此该算法的时间复杂度为O(n)。
因为单链表结构定义时没有定义表长,所以无法事先获知循环次数,因此不推荐使用for循环。该算法的主要核心是“当前工作指针”,这其实也是多数关于链表算法的核心思想。
4)单链表的插入与删除
单链表的插入与删除操作是单链表的优势之一。插入和删除操作无需像线性表的顺序存储结构一样,插入或删除一个节点需要影响到众多其他节点。
假设在单链表中,待插入节点的指针为s,s节点的前驱节点为p,则插入操作只需2步即可:
s->next=p->next;p->next=s;
但是注意,这两句顺序不可交换。
如果先让p->next=s;那么下一句s->next=p->next就相当于s->next=s,这样新加入节点s就无法接入它的后继节点了,“临场掉链子”。
单链表的第i个数据位置插入节点的算法思路:
⒈声明一个指针p指向链表头结点,初始化j从1开始
⒉当j<i时,遍历链表,即指针p不断向后移动
⒊若到链表末尾p为空,则位置i不存在
⒋p找到第i个位置,生成待插入空结点s
⒌将数据元素e赋值给s->data
⒍执行单链表的插入语句:s->next=p->next;p->next=s;
⒎返回成功
//代码见附录

接下来我们来看单链表的删除。假设第i个位置节点为q,它的前驱节点是p,现在要删除节点q,其实只需将q的前驱节点p绕过q节点指向q的后继节点即可:
q=p->next;p->next=q->next;
单链表的第i个数据位置删除节点的算法思路:
⒈声明一个指针p指向链表头结点,初始化j从1开始
⒉当j<i时,遍历链表,即指针p不断向后移动
⒊若到链表末尾p为空,则说明第i个位置的节点不存在
⒋p指向q的前驱节点,即q==p->next
⒌执行单链表的删除语句:p->next=q->next;
⒍将q节点中数据取出作为结果
⒎释放q节点
⒏返回成功
//代码见附录
分析单链表的插入和删除代码,我们可以发现,它们的算法其实都是由两部分组成:第一部分是遍历查找第i个节点,第二部分是对它进行相应的操作。而且我们可以看出,对于第i个节点的操作不会影响到其他位置的节点,这也是单链表比顺序表优势的地方。显然,对于插入/删除比较频繁的操作,单链表的效率要明显高于顺序表。
===============================================================================
4、顺序表与单链表的优缺点
//见附图2
通过对比,我们可以得出一些结论:
⒈若该线性表需要频繁进行查找操作,而很少进行插入/删除操作时,我们推荐采用顺序表存储。而若该线性表需要频繁进行插入/删除操作时,我们推荐使用单链表。例如在一款游戏中,玩家个人信息除注册时涉及到插入数据外,一般不会发生大的改变,因此我们使用顺序表存储。而玩家的装备列表则会随着玩家的游戏而发生改变,即随时会发生插入/删除操作,这时使用顺序表就不太合适,而应采用单链表。
⒉当线性表中的元素数量变化较大,或无法事先预制数目时,我们推荐使用单链表,这样可以无需考虑存储空间大小分配的问题。反之,若我们已事先知道了数据规模(例如1年有12月,1星期有7天等情况),则我们推荐使用顺序表,这样存储效率会高很多。
总之,顺序表与单链表各有其优缺点,需要在实际情况中权衡需要使用哪种方式。
===============================================================================
练习1:单链表反序
已有单链表L,编写函数使得单链表的元素反序存储。
提示:函数原型:int ListReverse(LinkList L)
//代码见附录
练习2:已有单链表L存放的数据类型为整型,其头结点为head,编写函数,求单链表中相邻两点数据data之和为最大的一对节点的第一节点的指针。
提示:函数原型:LinkList Adjmax(LinkList h)
//代码见附录
===============================================================================
===============================================================================
二、循环链表
若将单链表的尾节点的指针由空改成指向头结点,则将整个单链表形成了一个环,这种头尾相接的单链表称为单循环链表,简称循环链表(Circular linked list)。
循环链表解决了一个单链表存在的很麻烦的问题:如何从链表的任意节点出发,访问到链表的全部节点。
同单链表一样,为了解决单循环链表的空表与非空表操作一致问题,我们通常会设置一个头结点,该头结点里不存任何数据(或只存其他无关数据)。这样对于循环的判断结束条件就从p->next是否为空,变成了p->next是否为头结点。
//代码见附录
练习:使用单项循环链表求解约瑟夫环问题,其中人数n为33人,每逢m=7人枪毙一人,起始位置为第k=1个人
/***********约瑟夫环问题描述******************/
约瑟夫入狱,监狱内共有n=33个犯人。某日33名犯人围成一圈,从第k=1个犯人开始报数,报到数字m=7的犯人出列,被枪毙,下一名犯人重新从1开始报数。依次类推,直至剩下最后1名犯人可被赦免。聪明的约瑟夫在心里稍加计算,算出了最后枪毙的位置,他站在这个位置,最终避免了自己被枪毙,逃出升天。
问:约瑟夫算出的是哪个位置?
/***********约瑟夫环问题描述end***************/
#include <stdio.h>  #include <stdlib.h>  typedef int data_t;  /* use a cycle linked list without header node */  typedef struct node_t  {   data_t data;  struct node_t *next;  } linknode_t, *linklist_t;  //注意:该题目使用的为不带头结点的循环链表  int main()  {   int i, n, m, k;  linklist_t p, q;  printf("total N people will join this suicide game, please input N:");  scanf("%d", &n);  printf( "people stand in a circle, assume everyone is assigned\n"  "a sequence number from 1 to %d.\n"\  "which one would you like to start the number off (1~%d):", n, n);  scanf("%d", &k); printf("every Xth people should kill himself, please decide the X:");  scanf("%d", &m);  if (n < 1 || k > n || m < 1) {   printf("input error!\n");  return -1;  }  printf("game is starting ...\n");  /* added the first one */  //第一部分:创建n个人的循环链表  p = q = (linklist_t)malloc(sizeof(linknode_t));  p->data = 1;  /* added other left people */  for (i = 2; i <= n; i++) {   q->next = (linklist_t)malloc(sizeof(linknode_t));  q = q->next;  q->data = i;  }  /* complete the circle */  q->next = p;  /* find the people ahead of #k */  //第二部分:寻找起始位置  q = p;  while (q->next != p) {   if (q->next->data == k)//寻找起始位置k的前驱节点  break;  q = q->next;  }  //第三部分:开始Johsph环逻辑  while (q->next != q) { /* till the last one */  /* every m people */  for (i = 0; i < m - 1; i++)//删除m号节点需要寻找它的前驱(m-1号)节点  {   q = q->next;  }  /* kill the m-th people */  p = q->next;  q->next = p->next;  printf("%-2d was killed\n", p->data);  free(p);  }  /* kill the last one */  printf("%-2d was alive\n", q->data);  free(q);  return 0;  }
===============================================================================
===============================================================================
三、双向链表
我们在单链表中,有了next指针,它使得我们要查找某节点的下一个节点的时间复杂度为O(1)。可是若要查找某节点的上一个节点,那时间复杂度就是O(n)了。因为我们每次要查找某节点的上一个节点,必须从头指针开始遍历查找。
为了克服单向性这一缺陷,我们设计出了双向链表。双向链表(double linked list)是在单链表的每个节点中,再设置一个指向其前驱节点的指针域。所以在双向链表的每个节点都有两个指针域,一个指向直接后继,另一个指向直接前驱
/*双向链表的存储结构*/
typedef struct DulNode
{
data_t data;
struct DulNode *prior;
struct DulNode *next;
}DulNode,*DuLinkList;
由于双向链表的节点指针有两个,那么对于某节点p,它的后继的前驱是其本身,它的前驱的后继也是其本身,即:
p->next->prior = p = p->prior->next
因为双向链表是单链表扩展出来的结构,因此它的很多操作与单链表是基本相同的。比如获得位置i的节点的数据、遍历打印整个链表、求表长等操作,这些操作都只涉及到一个方向的指针(prior或next),另一个方向的指针基本无用,因此操作与单链表本身并无区别。
对于双向链表的插入/删除操作,需要更改两个指针变量,因此双向链表的插入/删除操作需要注意两个指针变量的操作顺序。
双向链表的插入操作:向节点p与p->next之间插入节点s
//见附图3
注意4步的顺序不能错:
①s->prior = p;
②s->next = p->next;
③p->next->prior = s;
④p->next = s;
由于第二步与第三步都涉及到p->next,如果先行执行第四步的话,会使得p->next节点提前变成s,使得后续的工作无法完成。所以,实现双向链表的插入操作的顺序是:先解决s的前驱和后继,再解决后节点的前驱,最后解决前节点的后继。
//代码见附录
双向链表的删除操作比较简单,若要删除节点p,只需两个步骤即可:
//见附图3
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
//代码见附录
对于单链表来说,双向链表要复杂一些,对于插入和删除操作要注意其操作顺序。另外每个节点都使用了额外的存储空间来存储前驱节点。但是双向链表有良好的对称性,而且对某节点的前驱节点操作要方便许多。
===============================================================================
===============================================================================
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xavier679/article/details/80878684

智能推荐

Android四大组件_爱吃猫的鱼101的博客-程序员秘密_安卓四大组件之一

Android四大组件Activity(活动)Service(服务)Broadcast Receive(广播接收者)Content Provider(内容提供者)1.Activity1.1定义:Activity是Android的四大组件之一。是用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。在Android App 中只要能看见的几乎都要依托于Activ

定了!FRM全部转为机考!_LYCLYC1的博客-程序员秘密_frm 考试形式

定了!FRM全部转为机考! www.gfedu.cn/frm凌晨的时候,各位FRM考生都收到了GARP协会的邮件,Important Updates to the 2021 FRM Exam,其中一个最重要的消息就是2021年FRM考试将过渡为机考模式!很快,GARP协会中国的官方公众号也官宣。大家可能对这突然的消息还有很多疑问,接下来请大家跟着FRM小编一起解读一下!什么是过渡为机考模式?协会邮件:首先FRM考试由于都是选择题,笔试切换为机考还是很方便的,再加上疫情的影响,考试全部转为机

数据库实战1 ---- Java进阶篇_旭日初扬的博客-程序员秘密_查询出姓名为“刘德华”的操作员具有哪些功能权限;

一.开发资料 建设工程监管信息系统资料 来源:数据库应用开发基础 教材 E-R图: 逻辑数据模型字段名称定义 字段名 字段说明 字段名 ...

【JAVA】LinkedHashSet集合的概念及其与LinkedHashMap有序的原因_浮_舍的博客-程序员秘密_linkedhashset为什么有序

LinkedHashSet集合特点LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。并且linkedHashSet是一个非线程安全的集合。如果有多个线程同时访问当前linkedhashset集合容器,并且有一个线程对当前容器中的元素做了修改,那么必须要在外部实现同步保证数据的冥等性。冥等性的理解:http://ww...

linux基础part5_weixin_30772261的博客-程序员秘密

linux 基础一、网络基础  1、ifup 网卡名称;ifdown 网卡名称;ifconfig 网卡名称 ip 子网 其修改只是临时生效,一旦关机或重启命令失效,需要修改配置文件永久生效。  2、网卡配置文件路径:/ect/sysconfig/network-scripts/  3、重新启动服务命令:systemctl restart 服务名称二、rpm包管理  1、rp...

Spring入门到精通:第四章 AOP:6.AOP基于注解实现切点表达式优化_悟纤的博客-程序员秘密_aop切点表达式 基于注解

我们上面的例子虽然基本实现了AOP的功能,但是存在很多待优化的地方。一、切点表达式优化(1)切入点表达式统一化 现在我们在不同的通知上都使用了切点表达式,不同的地方一样的表达式,那么是否可以写在一个地方呢,当然可以了,只要使用@Pointcut进行注解一个方法是一个切入点即可:@Pointcut("execution(double com.kfit.user.service.CalculatorService.add(double,double))")public void ...

随便推点

多线程run()中经常写while(true)的作用_谁的寂寞覆我华裳的博客-程序员秘密_线程while(true)可用吗

线程基础一直不太好,也没怎么用过,最近看到了一些线程的代码,发现一个现象,run()方法中基本都会写while(true)的循环,如下:public class XXXThread implements Runnable {public void run(){while(true) {……}}}使用while(true)的作用:run方法中的代码

小程序使用css变量,小程序中使用css var变量(使js可以动态设置css样式属性)_Cnh21198的博客-程序员秘密

使用sass,stylus可以很方便的使用变量来做样式设计,其实css也同样可以定义变量,在小程序中由于原生不支持动态css语法,so,可以使用css变量来使用开发工作变简单。基本用法基础用法page {--main-bg-color: brown;}.one {color: white;background-color: var(--main-bg-color);margin: 10px;}.t...

司马的流氓软件——极速输入法的删除办法_中南自动化学院“智能控制与优化决策“至渝的博客-程序员秘密_极速输入法怎么彻底删除

&nbsp; &nbsp; &nbsp; &nbsp; 换了新电脑,原来的微软拼音用得好好的,今天突然出来一个啥极速输入法,无法输入不说,还找不到怎么卸载,流氓的要死,最后找到怎么删掉他了步骤进入语言首选项,要么右键输入法哪儿进(有两个输入法的时候),要么控制面板-------时钟域区域---------区域---------语言首选项&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;找

【精彩推荐】RT-Thread操作系统μC/OS-III兼容层_RTThreadIoTOS的博客-程序员秘密

RT-Thread社区作者:满鉴霆1 概述这是一个针对RT-Thread操作系统的μCOS-III操作系统兼容层,可以让基于美国Micriμm公司的μCOS-III操作系统的项目快速迁移...

FFMPEG学习【libavutil】:数据结构(三)_一世豁然的博客-程序员秘密_ffmpeg child_next

AVOptions提供了一个通用的系统来声明任意结构(“对象”)上的选项。一、模块一)、Evaluating option strings这组函数可用于评估选项字符串并从中获取数字。它们与av_opt_set()执行相同的操作,除了将结果写入到调用者提供的指针中。参数:obj:一个结构体,其第一个元素是指向AVClass的指针。   o:要评估字符串的选

推荐文章

热门文章

相关标签