数据结构学习日记--双向链表

1.双向链表的模型

头节点无效、链表中每一个节点都有两个指针,分别指向前一个结点和后一个节点。

前驱指针:指向前一个节点的指针。

后驱指针:指向后一个节点的指针。

2.设计节点;

struct list_node
{
    /*数据域*/

    /*指针域*/
    struct list_node *next;
    struct list_node *prev;

}

3.双向链表的增删改查功能的实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list_node
{

    int num;
    struct list_node *next;
    struct list_node *prev;
};

struct list_node *init_list_head()
{
    struct list_node *head;
    head = malloc(sizeof(struct list_node));

    head->next = NULL;
    head->prev = NULL;
    return head;
}

void insert_list_head(struct list_node *head, int num)
{

    struct list_node *new = malloc(sizeof(struct list_node));
    new->num = num;
    new->next=NULL;
    new->prev=NULL;

    new->next = head->next;
    new->prev = head;
    if(head->next!=NULL){
        head->next->prev=new;
    }
    
    head->next = new;

    return;
}

void show_list_node(struct list_node *head)
{
    struct list_node *p = NULL;
    for (p = head->next; p != NULL; p = p->next)
    {
        printf("%d\n", p->num);
    }
    return;
}

void insert_list_last(struct list_node *head, int num)
{
    printf("#\n");
    struct list_node *new = malloc(sizeof(struct list_node));

    new->num = num;

    new->next = NULL;
    new->prev = NULL;

    struct list_node *q;
    for (q = head; q->next != NULL; q = q->next)
        ;
    q->next = new;
    new->prev = q;

    return;
}

void show_list_last(struct list_node *head)
{
    struct list_node *p = NULL;
    for (p = head; p->next != NULL; p = p->next)
        ;

    for (; p != head; p = p->prev)
    {

        printf("%d\n", p->num);
    }
    return;
}

void delete_list_node(struct list_node*head,int num){
    struct list_node*p=NULL;
    for(p=head->next;p!=NULL;p=p->next){
        if(p->num==num){
            p->prev->next=p->next;
            if(p->next!=NULL){
                p->next->prev=p->prev;
            }
            free(p);
        }
    }
    return;
}

void delete_list(struct list_node*head){
    struct list_node*p=NULL;
    struct list_node*q=NULL;

    for(p=q=head;p!=NULL;p=q){
        q=p->next;
        free(p);
    }
    return;
}

int main()
{
    struct list_node *head = init_list_head();

    

    //向后遍历
    // show_list_node(head);

    //尾插
    insert_list_last(head, 40);
    insert_list_last(head, 50);
    insert_list_last(head, 60);
    //头插
    insert_list_head(head, 10);
    insert_list_head(head, 20);
    insert_list_head(head, 30);


    //向前遍历
    // show_list_node(head);
    show_list_last(head);
    printf("___________\n");

    //删除节点
    delete_list_node(head,20);
    show_list_last(head);


    //删除整条链表
    delete_list(head);
    return 0;
}

使用双向链表实现的小程序功能

在开发板根目录下,有一个目录叫bmp_data/,里面有很多张bmp格式图片,但是有多少张,我们不知道。 要求使用双向链表来储存数据。 1)当程序执行后,显示第一张图片。 2)点击最左边的区域,就显示上一张,点击最右边区域,显示下一张。 3)点击中间偏下的区域,那么程序就结束。 4)点击中间偏上的区域,那么就删除当前正在显示的这张图片,显示下一张图片。 例如: 1.bmp 2.bmp 3.bmp 4.bmp 5.bmp 正在显示

        第一步:点击删除,就会显示3.bmp
                第二步:点击左边区域,就会显示1.bmp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

struct list_node{
	char picname[20];
	struct list_node *next;
	struct list_node *prev;
};

struct list_node *init_list_head()
{
	//1. 为头节点申请空间。
	struct list_node *head = malloc(sizeof(struct list_node));

	//2. 为头节点赋值。
	head->next = NULL;
	head->prev = NULL;

	return head;
}

void insert_picname_to_list(struct list_node *head,char *picname)
{
	//1. 为新节点赋值。
	struct list_node *new = malloc(sizeof(struct list_node));

	//2. 为数据域与指针域赋值。
	strcpy(new->picname,picname);
	new->next = NULL;

	//3. 寻找最后一个节点
	struct list_node *p = NULL;
	for(p=head;p->next!=NULL;p=p->next);

	//4. 处理指针关系。
	p->next = new;
	new->prev = p;

	return;
}

void show_list_node(struct list_node *head)
{
	struct list_node *p = NULL;
	for(p=head->next;p!=NULL;p=p->next)
	{
		printf("p->picname:%s\n",p->picname);
	}
	return;
}


void mmap_show_bmp(const char *picname)
{
	char bmp_buf[800*480*3] = {0};  //图片每一个像素点都是由3个字节组成,所以一共有800*480*3个字节。
	char lcd_buf[800*480*4] = {0};  //lcd每一个像素点都是由4个字节组成,所以一共有800*480*4个字节。
	char show_buf[800*480*4] = {0};
	int x,y;
	int i,j,k;

	//1. 访问图片文件。
	FILE *fp = fopen(picname,"r");  //当前的光标在最开头
	if(fp == NULL)
		printf("fopen error!\n");

	//2. 访问lcd液晶设备
	int lcd = open("/dev/fb0",O_RDWR);
	if(lcd < 0)
		printf("open lcd error!\n");

	//3. 跳过54个头数据。
	fseek(fp,54,SEEK_SET);

	//4. 将图片的数据读取到一个缓冲区中。
	int n = fread(bmp_buf,800*480*3,1,fp);
	if(n != 1)
		printf("fread error!\n");

	//5. 24位转32位
	for(i=0,j=0;i<800*480*4;i+=4,j+=3)
	{
		lcd_buf[i] = bmp_buf[j];
		lcd_buf[i+1] = bmp_buf[j+1];
		lcd_buf[i+2] = bmp_buf[j+2];
		lcd_buf[i+3] = 0;
	}

	//6. 上下颠倒
	for(y=0;y<480;y++)
	{
		for(x=0;x<800*4;x++)
		{
			show_buf[800*4*(479-y)+x] = lcd_buf[800*4*y+x];
		}
	}

	//7. 内存映射
	char *p = mmap(NULL,800*480*4,PROT_WRITE|PROT_READ,MAP_SHARED,lcd,0);
	if(p == (void *)-1)
		printf("mmap error!\n");

	//8. 不断将show_buf的内容拷贝到内存空间。
	for(k=0;k<800*480*4;k++)
	{
		memcpy(p+k,&show_buf[k],1);
	}
	
	//9. 撤销映射
	munmap(p,800*480*4);

	//10.关闭文件。
	close(lcd);
	fclose(fp);

	return;
}

int delete_list_node(struct list_node *head,char *del_picname)
{
	struct list_node *p = NULL;
	struct list_node *q = NULL;

	for(q=head,p=head->next;p!=NULL;q=p,p=p->next)
	{
		if(strcmp(p->picname,del_picname) == 0)
		{
			q->next = p->next;
			if(p->next!=NULL)
				p->next->prev = q;

			free(p);
			return 0;
		}
	}
	return -1;
}


int main(int argc,char *argv[])
{
	//1. 初始化链表头
	struct list_node *head = NULL;
	head = init_list_head();

	//2. 打开目录。
	DIR *dp = opendir("./bmp_data");
	if(dp == NULL)
		printf("opendir error!\n");

	//3. 切换目录。
	chdir("./bmp_data");

	//4. 不断读取目录。
	struct dirent *ep = NULL;
	while(1)
	{
		ep = readdir(dp);
		if(ep == NULL)
			break;
		if(ep->d_name[0] == '.')
			continue;
		insert_picname_to_list(head,ep->d_name);
	}

	//5. 遍历链表。
	//show_list_node(head);
	
	//5. 显示第一张图片。
	struct list_node *p = head->next;
	mmap_show_bmp(p->picname);

	//5.5 找到最后一张的指针。
	struct list_node *tmp = NULL;
	struct list_node *last;

	//6. 进入触摸屏状态。
	int ts = open("/dev/input/event0",O_RDWR);

	//7. 读取触摸屏的数据。
	struct input_event buf;
	int x,y;
	while(1)
	{
		read(ts,&buf,sizeof(buf));
		if(buf.type == 3 && buf.code == 0)
		{
			x = buf.value;
		}

		if(buf.type == 3 && buf.code == 1)
		{
			y = buf.value;
		}

		if(buf.type == 1 && buf.code == 330 && buf.value == 0)
		{
			for(last=head;last->next!=NULL;last=last->next);
			
			if(x < 300)  //上一张
			{
				if(p->prev == head)  //说明当前正在显示第一张
				{
					p = last;
				}
				else{
					p = p->prev;
				}
				mmap_show_bmp(p->picname);
			}

			if(x > 724)  //下一张
			{
				if(p->next == NULL)
				{
					p = head->next;
				}
				else{
					p = p->next;
				}
				mmap_show_bmp(p->picname);
			}

			if(x > 300 && x < 724 && y > 300)
			{
				break;
			}

			if(x > 300 && x < 724 && y < 300)
			{
				tmp = p->next;
				if(tmp == NULL)
				{
					tmp = head->next;
				}
				mmap_show_bmp(tmp->picname);
				delete_list_node(head,p->picname);
				p = tmp;	
			}	
		}
	}

	return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值