链表(数据结构)- LRC歌词解析播放示例

链表与数组

  • 链表和数组一样也是线性表的一种,所谓线性表是指零个或多个数据元素的序列,序列元素之间有明显的前驱后继关系。
  • 但链表与数组不一样的是,链表是通过指针域串联起来的,而数组是通过一片连续的存储空间串联起来,数组元素的地址有着明显的线性关系,而链表元素地址之间则没有关系。使用数组需要预先分配一片连续的存储空间,而链表则可以无限制的加入新的结点。
  • 本文将介绍通用单向链表、单向循环链表、双向链表的实现方法。

LRC歌词解析播放(单向链表)

/*************************************************************************
	> File Name: lrcLinkList.c
	> Author: mrhjlong
	> Mail: mrhjlong@163.com 
	> Created Time: 2016年04月19日 星期二 12时57分07秒
 ************************************************************************/

/*读取lrc文件歌词数据到单向链表中,并能按时间打印出来。*/

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>

//链表结点结构类型
struct lrcNode
{
	int minute;				//数据域
	int second;
	char data[60];
	
	struct lrcNode *next;	//指针域
};

//链表头结构类型
struct lrcLinkHead
{
	struct lrcNode *lrcHead;
};

typedef struct lrcNode LrcNode;			//链表结点类型重命名
typedef struct lrcLinkHead LrcLinkHead;	//链表头类型重命名


//创建链表的头指针
LrcLinkHead *lrcHead_create()
{
	LrcLinkHead *lrcLinklist = (LrcLinkHead *)malloc(sizeof(LrcLinkHead));
	lrcLinklist->lrcHead = NULL;
	return lrcLinklist;
}

//创建链表的结点,并给结点的数据域赋值
LrcNode *lrcNode_create(int minute, int second, char data[])
{
	LrcNode *pLrcNode = (LrcNode *)malloc(sizeof(LrcNode));
	assert(pLrcNode);

	pLrcNode->minute = minute;
	pLrcNode->second = second;

	memset(pLrcNode->data, '\0', sizeof(pLrcNode->data));
	strcpy(pLrcNode->data, data);
	
	pLrcNode->next = NULL;

	return pLrcNode;
}


//添加链表结点头指针所指向的链表的链表头
void lrcNode_insert_head(LrcLinkHead *lrcLinklist, LrcNode *pLrcNode)
{
	if(lrcLinklist->lrcHead == NULL)
	{
		lrcLinklist->lrcHead = pLrcNode;
	}
	else
	{
		pLrcNode->next = lrcLinklist->lrcHead;
		lrcLinklist->lrcHead = pLrcNode;
	}
}

//添加链表结点到头指针所指向的链表的尾部
void lrcNode_insert_tail(LrcLinkHead *lrcLinklist, LrcNode *pLrcNode)
{
	if(lrcLinklist->lrcHead == NULL)
	{
		lrcLinklist->lrcHead = pLrcNode;
	}
	else
	{
		LrcNode *p = lrcLinklist->lrcHead;
		while(p->next != NULL)
		{
			p = p->next;
		}
		p->next = pLrcNode;
	}
}

//查找链表结点的数据域(时间),查找成功返回结点的首地址,查找失败返回NULL
LrcNode *lrcNode_search(LrcLinkHead *lrcLinklist, int minute, int second)
{
	LrcNode *p = lrcLinklist->lrcHead;
	while(p != NULL)
	{
		if(p->minute == minute && p->second == second)
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}

//删除链表中的指定结点
void lrcNode_delete(LrcLinkHead *lrcLinklist, LrcNode *pLrcNode)
{
	LrcNode *p = lrcLinklist->lrcHead;
	LrcNode *temp = NULL;

	if(p == pLrcNode)
	{
		lrcLinklist->lrcHead = p->next;
		free(p);
	}
	else
	{
		while(p->next != NULL)
		{
			if(p->next == pLrcNode)
			{
				temp = p->next;
				p->next = p->next->next;
				free(temp);
				return;
			}
			p = p->next;
		}
	}
}

//按数据域的时间,逐次打印整张链表的数据域
void lrcNode_print(LrcLinkHead *lrcLinklist)
{
	LrcNode *p = lrcLinklist->lrcHead;
	int timePrv = 0;
	int time = 0;

	while(p != NULL)
	{
		time = (p->minute) * 60 + p->second;
		sleep(time - timePrv);
		timePrv = time;

		if(p->minute < 10 && p->second < 10)
			printf("[0%d:0%d]%s", p->minute, p->second, p->data);
		else if(p->minute < 10)
			printf("[0%d:%d]%s", p->minute, p->second, p->data);
		else if(p->second < 10)
			printf("[%d:0%d]%s", p->minute, p->second, p->data);
		else
			printf("[%d:%d]%s", p->minute, p->second, p->data);
		
		p = p->next;
	}
}

//销毁整张链表,释放堆内存
void lrcList_destroy(LrcLinkHead *lrcLinklist)
{
	LrcNode *p = lrcLinklist->lrcHead;
	LrcNode *temp = NULL;

	while(p != NULL)
	{
		temp = p->next;
		free(p);
		p = temp;
	}
	free(lrcLinklist);
}

//创建链表,读取lrc文件内容,依次添加到链表当中
LrcLinkHead  *create_lrcLinklist(FILE *fp)
{
	LrcLinkHead *lrcLinklist = lrcHead_create();
	assert(lrcLinklist);

	LrcNode *pLrcNode = NULL;
	char buffer[100] = {0};
	int minute, second;	
	char *p = NULL;

	p = fgets(buffer, 100, fp);
	while(p != NULL)
	{
		if(buffer[0] == '[' && buffer[1] >='0' && buffer[1] <= '9')
		{
			minute = (buffer[1] - '0') * 10 + (buffer[2] - '0');
			second = (buffer[4] - '0') * 10 + (buffer[5] - '0');

			pLrcNode = lrcNode_create(minute, second, buffer + 10);
			assert(pLrcNode);
			lrcNode_insert_tail(lrcLinklist, pLrcNode);
		}
		memset(buffer, '\0', sizeof(buffer));
		p = fgets(buffer, 100, fp);
	}

	return lrcLinklist;
}

int main()
{
	FILE *fp = NULL;
	fp = fopen("如烟.lrc", "r");
	if(fp == NULL)
	{
		printf("open file error!\n");
		assert(fp);
	}

	LrcLinkHead  *lrcLinklist = create_lrcLinklist(fp);
	assert(lrcLinklist);

	lrcNode_print(lrcLinklist);
	lrcList_destroy(lrcLinklist);
	
	return 0;
}

歌词解析播放效果:

mrhjlong@hjl-virtual-machine:day2$ ./a.out 
[00:02]如烟 - 五月天
[00:04]作词:石头、阿信 
[00:06]作曲:石头、阿信
[00:08]
[00:10]我坐在床前
[00:13]望着窗外回忆满天
[00:20]生命是华丽错觉
[00:23]时间是贼偷走一切
[00:30]
[00:30]七岁的那一年
[00:33]抓住那只蝉

单向链表

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int type_t;         //链表数据类型重命名

struct node{                //链表结点类型
    type_t data;            //数据域
    struct node *next;      //指针域 
};

struct link_head            //链表头结构类型
{
    struct node *head;
};

typedef struct node Node;           //链表类型重命名
typedef struct link_head Link_head;

//创建链表的头指针
Link_head *head_create();

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data);

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode);
	
//创建链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode);

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data);

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode);

//打印整张链表数据域
void node_print(Link_head *linklist);

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist);

int main()
{
	Link_head *linklist = head_create();
	assert(linklist);

	Node *pnode1 = node_create(1);
	assert(pnode1);
	Node *pnode2 = node_create(2);
	assert(pnode2);
	node_insert_tail(linklist, pnode1);
	node_insert_tail(linklist, pnode2);

	Node *pnode3 = node_search(linklist, 2);
	printf("%p\n%p\n", pnode3, pnode2);
	node_print(linklist);
	node_delete(linklist, pnode2);
	node_delete(linklist, pnode1);

	Node *pnode4 = node_create(4);
	assert(pnode4);
	Node *pnode5 = node_create(5);
	assert(pnode5);
	node_insert_tail(linklist, pnode4);
	node_insert_head(linklist, pnode5);
	node_print(linklist);
	list_destroy(linklist);

	return 0;
}


//创建链表的头指针
Link_head *head_create()
{
	Link_head *linklist = (Link_head *)malloc(sizeof(Link_head));
	linklist->head = NULL;
	return linklist;
}

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data)
{
	Node *pnode = (Node *)malloc(sizeof(Node));
	assert(pnode);
	pnode->data = data;
	pnode->next = NULL;
	return pnode;
}

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
	}
	else
	{
		pNode->next = linklist->head;
		linklist->head = pNode;
	}
	printf("insert a node at head! Data is %d\n", pNode->data);
}

//添加链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
	}
	else
	{
		Node *p = linklist->head;
		while(p->next != NULL)
			p = p->next;

		p->next = pNode;
	}
	printf("insert a node at tail! Data is %d\n", pNode->data);
}

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data)
{
	Node *p = linklist->head;
	while(p != NULL)
	{
		if(p->data == data)
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode)
{
	printf("Deleting a node! Data is %d\n", pNode->data);
	Node *p = linklist->head;
	Node *temp = NULL;
	if(p == pNode)
	{
		linklist->head = p->next;
		free(p);
	}
	else
	{
		while(p->next != NULL)
		{
			if(p->next == pNode)
			{
				temp = p->next;
				p->next = p->next->next;
				free(temp);
				return;
			}
			p = p->next;
		}
	}
}

//打印整张链表数据域
void node_print(Link_head *linklist)
{
	printf("Print linklist:\n");
	Node *p = linklist->head;
	while(p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\nPrint Done!\n");
}

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist)
{
	Node *p = linklist->head;
	Node *temp = NULL;

	while(p != NULL)
	{
		temp = p->next;
		free(p);
		p = temp;
	}
	free(linklist);
	printf("linklist destroy Done!\n");
}

单向循环链表

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int type_t;         //链表数据类型重命名

struct node{                //链表结点类型
    type_t data;            //数据域
    struct node *next;      //指针域 
};

struct link_head            //链表头结构类型
{
    struct node *head;
	struct node *tail;
};

typedef struct node Node;           //链表类型重命名
typedef struct link_head Link_head;

//创建链表的头指针
Link_head *head_create();

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data);

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode);
	
//创建链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode);

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data);

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode);

//打印整张链表数据域
void node_print(Link_head *linklist);

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist);

int main()
{
	Link_head *linklist = head_create();
	assert(linklist);

	Node *pnode1 = node_create(1);
	assert(pnode1);
	Node *pnode2 = node_create(2);
	assert(pnode2);
	node_insert_tail(linklist, pnode1);
	node_insert_tail(linklist, pnode2);
	//Node *pnode3 = node_search(linklist, 2);
	//printf("%p\n%p\n", pnode3, pnode2);
	node_print(linklist);


	//node_delete(linklist, pnode2);
	//node_delete(linklist, pnode1);
	Node *pnode4 = node_create(4);
	assert(pnode4);

	node_insert_head(linklist, pnode4);
	node_print(linklist);

	printf("%d\n", pnode2->next->data);
	//list_destroy(linklist);

	return 0;
}


//创建链表的头指针
Link_head *head_create()
{
	Link_head *linklist = (Link_head *)malloc(sizeof(Link_head));
	linklist->head = NULL;
	linklist->tail = NULL;
	return linklist;
}

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data)
{
	Node *pnode = (Node *)malloc(sizeof(Node));
	assert(pnode);
	pnode->data = data;
	pnode->next = NULL;
	return pnode;
}

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
		linklist->tail = pNode;
		pNode->next = pNode;
	}
	else
	{
		linklist->tail->next = pNode;
		pNode->next = linklist->head;
		linklist->head = pNode;
	}
}

//添加链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
		linklist->tail = pNode;
		pNode->next = pNode;
	}
	else
	{
		linklist->tail->next = pNode;
		pNode->next = linklist->head;
		linklist->tail = pNode;
	}
}

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data)
{
	Node *p = linklist->head;
	while(p != NULL)
	{
		if(p->data == data)
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode)
{
	Node *p = linklist->head;
	Node *temp = NULL;
	if(p == pNode)
	{
		linklist->head = p->next;
	}
	else
	{
		while(p->next != NULL)
		{
			if(p->next == pNode)
			{
				temp = p->next;
				p->next = p->next->next;
				free(temp);
				return;
			}
			p = p->next;
		}
	}
}

//打印整张链表数据域
void node_print(Link_head *linklist)
{
	Node *p = linklist->head;
	do
	{
		printf("%d ", p->data);
		p = p->next;
	}while(p != linklist->head);
	printf("\n");
}

void node_print_by_node(Node *pNode)
{
	Node *p = pNode;
	do
	{
		printf("%d ", p->data);
		p = p->next;
	}while(p != pNode);
	printf("\n");
}

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist)
{
	Node *p = linklist->head;
	Node *temp = NULL;

	while(p != NULL)
	{
		temp = p->next;
		free(p);
		p = temp;
	}
	free(linklist);
}

双向链表

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int type_t;         //链表数据类型重命名

struct node{                //链表结点类型
    type_t data;            //数据域
    struct node *next;      //指针域 
	struct node *prev;
};

struct link_head            //链表头结构类型
{
    struct node *head;
};

typedef struct node Node;           //链表类型重命名
typedef struct link_head Link_head;

//创建链表的头指针
Link_head *head_create();

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data);

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode);
	
//创建链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode);

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data);

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode);

//打印整张链表数据域
void node_print(Link_head *linklist);

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist);

int main()
{
	Link_head *linklist = head_create();
	assert(linklist);

	Node *pnode1 = node_create(1);
	assert(pnode1);
	Node *pnode2 = node_create(2);
	assert(pnode2);
	node_insert_tail(linklist, pnode1);
	node_insert_tail(linklist, pnode2);

	Node *pnode3 = node_search(linklist, 2);
	printf("%p\n%p\n", pnode3, pnode2);
	node_print(linklist);

	node_delete(linklist, pnode2);
	node_delete(linklist, pnode1);

	Node *pnode4 = node_create(4);
	assert(pnode4);
	Node *pnode5 = node_create(5);
	assert(pnode5);
	node_insert_tail(linklist, pnode4);
	node_insert_head(linklist, pnode5);

	node_print(linklist);
	list_destroy(linklist);

	return 0;
}


//创建链表的头指针
Link_head *head_create()
{
	Link_head *linklist = (Link_head *)malloc(sizeof(Link_head));
	linklist->head = NULL;
	return linklist;
}

//创建链表的结合点并给结点的数据域赋值为data
Node *node_create(type_t data)
{
	Node *pnode = (Node *)malloc(sizeof(Node));
	assert(pnode);
	pnode->data = data;
	pnode->next = NULL;
	pnode->prev = NULL;
	return pnode;
}

//添加链表结点头指针所指向的链表的链表头
void node_insert_head(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
	}
	else
	{
		pNode->next = linklist->head;
		linklist->head->prev = pNode;
		linklist->head = pNode;
	}
	//printf("insert a node at head! Data is %d\n", pNode->data);
}

//添加链表结点到头指针所指向的链表的尾部
void node_insert_tail(Link_head *linklist, Node *pNode)
{
	if(linklist->head == NULL)
	{
		linklist->head = pNode;
	}
	else
	{
		Node *p = linklist->head;
		while(p->next != NULL)
			p = p->next;

		p->next = pNode;
		pNode->prev = p;
	}
	//printf("insert a node at tail! Data is %d\n", pNode->data);
}

//查找链表结点的数据域,查找成功返回结点的首地址,查找失败返回NULL
Node *node_search(Link_head * linklist, type_t data)
{
	Node *p = linklist->head;
	while(p != NULL)
	{
		if(p->data == data)
		{
			return p;
		}
		p = p->next;
	}
	return NULL;
}

//删除链表中的指定结点
void node_delete(Link_head *linklist, Node *pNode)
{
	printf("Deleting a node! Data is %d\n", pNode->data);
	Node *p = linklist->head;
	Node *temp = NULL;
	if(p == pNode)
	{
		linklist->head = p->next;
		free(p);
	}
	else
	{
		while(p->next != NULL)
		{
			if(p->next == pNode)
			{
				temp = p->next;
				p->next = p->next->next;
				free(temp);
				return;
			}
			p = p->next;
		}
	}
}

//打印整张链表数据域
void node_print(Link_head *linklist)
{
	printf("Print linklist:\n");
	Node *p = linklist->head;
	while(p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\nPrint Done!\n");
}

//销毁整张链表,释放堆内存
void list_destroy(Link_head *linklist)
{
	Node *p = linklist->head;
	Node *temp = NULL;

	while(p != NULL)
	{
		temp = p->next;
		free(p);
		p = temp;
	}
	free(linklist);
	printf("linklist destroy Done!\n");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值