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