10.3-4 实现ALLOCATE和FREE,使双向链表在多数组表示法中在存储器保持紧凑,占前n个位置。

10.3-4
实现ALLOCATE和FREE,使双向链表在多数组表示法中在存储器保持紧凑,占前n个位置。
自由表Free初始化:0,1,2,...
其实是一个stack。0是栈顶元素,Free是栈顶指针。下一个被分配之对象是最后被释放的。
自由表只使用next数组。Free和双链表L交错。

地址是数组下标,int类型。

看了这篇blog,我就有灵感了。

#include<stdio.h>
#define NIL -1
#define MAX 11
int Free;//自由表表头
int L;//双链表表头
int m;//L的元素个数。L新增结点时,m++。
typedef char ElemType;
int next[MAX];//后继
ElemType key[MAX];//值
int prev[MAX];//前驱
void error(const char*const s)
{
    puts(s);exit(1);
}
void initial()
{
    L=NIL;Free=0;m=0;
    int i;
    //整个数组都属于自由表,含MAX个未分配对象
    for(i=1;i<MAX;i++) next[i-1]=i;
    next[MAX-1]=NIL;
}
int ALLOCATE()
{//分配Free表头对象(栈顶)
    if(Free==NIL) error("Out of space.");
    else{
        int space=Free;Free=next[Free];m++;
        return space;
    }
}
void FREE(int p)
{/*在释放前,双链表L紧凑占据数组前m个位置。
    释放后,L应紧凑占据前m-1个位置。
    若p是第0~2个,则要将第m-1个位置的元素挪到p的位置;
    若p是第m-1个,就不需挪。然后修改prev,next指针,和Free。
    Free表头变成了新增的m。*/
    if(p<0||p>m-1) error("Wrong index.");
/*将数组中第m-1个位置元素挪到第p位。L中各元素的逻辑顺序不变。
只是物理地址为m-1的元素,物理地址变为p。*/
    if(p!=m-1){//printf("%d\n",p);//system("pause");
        key[p]=key[m-1];next[p]=next[m-1];prev[p]=prev[m-1];
        if(prev[p]!=NIL) next[prev[p]]=p;
        else L=p;
        if(next[p]!=NIL) prev[next[p]]=p;
    }
    next[m-1]=Free;Free=m-1;m--;
}
void insert(ElemType elem)
{//在L中插入元素
    int space=ALLOCATE();
    key[space]=elem;next[space]=L;prev[space]=NIL;
    if(L!=NIL) prev[L]=space;
    L=space;
}
int search(ElemType elem)
{
    int i;
    for(i=L;i!=NIL;i=next[i]) if(key[i]==elem) return i;
    return NIL;
}
void delete(ElemType elem)
{//删除第一个给定值的结点
    int index=search(elem);
    if(index!=NIL){
        if(prev[index]!=NIL) next[prev[index]]=next[index];
        else L=next[index];
        if(next[index]!=NIL) prev[next[index]]=prev[index];
        FREE(index);
    }
}
void traverse()
{
    int i;
    for(i=0;i<MAX;i++) printf("%3d",prev[i]);putchar('\n');
    for(i=0;i<MAX;i++) printf("  %c",key[i]);putchar('\n');
    for(i=0;i<MAX;i++) printf("%3d",next[i]);putchar('\n');
    printf("L:%3d    m:%3d    Free:%3d",L,m,Free);//system("pause");
    putchar('\n');
    for(i=L;i!=NIL;i=next[i]) putchar(key[i]);putchar('\n');
    if(L!=NIL){
        for(i=L;next[i]!=NIL;i=next[i]);
        for(;i!=NIL;i=prev[i]) putchar(key[i]);putchar('\n');
    }
    for(i=Free;i!=NIL;i=next[i]) printf("%3d",i);putchar('\n');putchar('\n');
}
int main(void)
{
    int free;//自由表表头
    int L;//双链表表头
    initial();

    insert('a');insert('b');insert('c');insert('d');
    insert('e');insert('f');insert('g');

    traverse();
    delete('g');delete('c');
    delete('a');traverse();
    insert('y');insert('z');traverse();
    delete('z');insert('x');traverse();
    insert('b');insert('b');insert('b');insert('b');
    traverse();delete('y');traverse();
    insert('a');insert('a');traverse();insert('a');
    return 0;
}


首先,需要了解bitstream filter是什么。bitstream filter是FFmpeg的一个模块,它可以在解码之前或编码之后操作码流数据。它可以用于对码流数据进行修改、过滤或修复。 下面是一个简单的示例代码,演示如何实现一个bitstream filter以处理H.264和HEVC码流数据,产生NAL header错误的码流。 ```c #include <libavcodec/avcodec.h> #include <libavutil/opt.h> typedef struct { AVBSFContext *bsf; } NalHeaderBSFContext; static int nal_header_filter(AVBSFContext *bsf, AVPacket *pkt) { uint8_t *data = pkt->data; int size = pkt->size; int i; for (i = 0; i < size - 5; i++) { if (data[i] == 0 && data[i+1] == 0 && data[i+2] == 0 && data[i+3] == 1) { // Found a NAL unit header if (data[i+4] != 0x41) { // Replace the NAL unit type data[i+4] = 0x41; } } } return av_bsf_send_packet(bsf, pkt); } static int nal_header_init(AVBSFContext *bsf) { NalHeaderBSFContext *ctx = bsf->priv_data; AVCodecParameters *par_in = bsf->par_in; if (par_in->codec_id != AV_CODEC_ID_H264 && par_in->codec_id != AV_CODEC_ID_HEVC) { av_log(bsf, AV_LOG_ERROR, "Only H.264 and HEVC are supported.\n"); return AVERROR(EINVAL); } return 0; } static int nal_header_close(AVBSFContext *bsf) { NalHeaderBSFContext *ctx = bsf->priv_data; av_bsf_free(&ctx->bsf); return 0; } AVBitStreamFilter ff_nal_header_bsf = { .name = "nal_header", .priv_data_size = sizeof(NalHeaderBSFContext), .filter = nal_header_filter, .init = nal_header_init, .close = nal_header_close, }; ``` 这个bitstream filter将遍历每个NAL单元的头,如果不是类型0x41,就将其替换为0x41。然后调用av_bsf_send_packet将包发送到下一个过滤器。 要使用这个bitstream filter,需要将其注册到FFmpeg,并在编码或解码时使用它。以下是如何使用它的示例代码: ```c #include <libavformat/avformat.h> int main(int argc, char *argv[]) { AVFormatContext *fmt_ctx = NULL; AVStream *stream = NULL; AVCodecParameters *codecpar = NULL; AVBSFContext *bsf_ctx = NULL; AVPacket pkt; int ret; av_register_all(); // Open the input file ret = avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n"); return ret; } // Find the first video stream ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot find video stream\n"); return ret; } stream = fmt_ctx->streams[ret]; codecpar = stream->codecpar; // Create the bitstream filter context ret = av_bsf_alloc(&ff_nal_header_bsf, &bsf_ctx); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot allocate bitstream filter\n"); return ret; } // Set the input and output codec parameters ret = avcodec_parameters_copy(bsf_ctx->par_in, codecpar); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot copy input codec parameters\n"); return ret; } ret = avcodec_parameters_copy(bsf_ctx->par_out, codecpar); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot copy output codec parameters\n"); return ret; } // Initialize the bitstream filter ret = av_bsf_init(bsf_ctx); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot initialize bitstream filter\n"); return ret; } // Read packets from the input file, filter them and write them to the output file while (av_read_frame(fmt_ctx, &pkt) == 0) { if (pkt.stream_index == stream->index) { // Filter the packet ret = av_bsf_send_packet(bsf_ctx, &pkt); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot send packet to bitstream filter\n"); break; } while (av_bsf_receive_packet(bsf_ctx, &pkt) == 0) { // Write the packet to the output file av_write_frame(out_fmt_ctx, &pkt); av_packet_unref(&pkt); } } av_packet_unref(&pkt); } // Flush the bitstream filter ret = av_bsf_send_packet(bsf_ctx, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot flush bitstream filter\n"); } while (av_bsf_receive_packet(bsf_ctx, &pkt) == 0) { // Write the packet to the output file av_write_frame(out_fmt_ctx, &pkt); av_packet_unref(&pkt); } // Free the bitstream filter context av_bsf_free(&bsf_ctx); // Close the input file avformat_close_input(&fmt_ctx); return 0; } ``` 这个示例代码从输入文件读取AVPacket,对视频流的包进行过滤,并将过滤后的包写入输出文件。在循环,当收到EOF时,它会调用av_bsf_send_packet发送NULL包来刷新bitstream filter。 以上是一个简单的示例,如果需要更复杂的过滤器,可以参考FFmpeg其他bitstream filter的实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值