-
链表介绍
- c语言的单向链表翻转是面试官常问问题之一;
- 链表和数组一样都是存储数据,链表是非连续,非顺序的存储结构;
- 链表是灵活的内存动态管理(随机分配空间),删除创建结点非常方便;
- 链表组成:由一系列结点组成;
- 链表结点:实际上是结构体变量。
typedef struct _LINKNODE
{
int data; // 数据域
struct _LINKNODE *next; // 指针域
}Link_Node;
- 链表结点包含两个部分:
- 1.存储数据元素的数据域(结构体),
- 2.存储下一个结点地址的指针域.
-
链表和数组的区别
- 数组:一次性分配连续的存储区域,int num[60] = {0};
- 优点:随机访问元素效率高
- 缺点:
- l开辟内存过大时,易分配失败
- l插入和删除元素效率低下
- 链表:无需一次性分配连续的存储空间,只需要分配n快结点存储区域,通过指针建立联系
- 优点:
- 不需要一次性分配连续的存储区域
- l删除和插入效率高
- 缺点:
- 随机访问元素效率低
-
链表分类
-
静态链表和动态链表
- 链表按照线性表链式存储结构分为静态链表和动态链表
- 静态链表:是在初始化的时候分配好足够的内存空间,存储空间是静态的,分配在栈上,模拟数组实现的,是顺序的存储结构
- 动态链表:是动态申请内存的,每个节点物理地址不连续
-
实现代码
#ifndef __LINK_LIST_H
#define __LINK_LIST_H
#define TAIL //#define HEAD 采用头插法创建链表,#define TAIL 采用尾插法创建链表
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
typedef struct Link_List
{
int data;
struct Link_List *next;
}L_list;
L_list * create_list(L_list * L, int data);
L_list * delete_data(L_list* L, int pose);
L_list * insert_data(L_list* L, int pose, int data);
void foreach(L_list * L);
#endif /* end of ifndef __LINK_LIST_H */
int main(int argc, char *argv[])
{
L_list * L1;
L_list * L2;
L_list * L3;
int data;
L2 = create_list(L1, data); //创建链表
L3 = insert_data(L2, 3, 50); //按位插入元素
puts("Before delete:");
foreach(L3); //遍历链表
L3 = delete_data(L3, 3); //按位删除元素
puts("After delete:");
foreach(L3);
return 0;
}/* end of main */
#ifndef HEAD
L_list * create_list(L_list * L, int data) //#define HEAD 采用尾插法创建链表
{
puts("Head insert:");
L_list * head;
head = malloc(sizeof(L_list));
head ->data = 20;
head ->next = NULL;
L = head;
for (data = 20; data <30;data++)
{
L_list * newNode = malloc(sizeof(L_list));
L -> next = newNode;
L = newNode;
newNode -> data = data;
newNode -> next =NULL;
}
return head;
}
#endif /* end of define HEAD*/
#ifndef TAIL
L_list * create_list(L_list * L, int data) //#define TAIL 采用头插法创建链表
{
puts("Tail insert:");
L_list * tail;
L = malloc(sizeof(L_list));
tail = L;
L ->data = 20;
L ->next = NULL;
for (data = 20; data < 30 ;data++)
{
L_list * newNode = malloc(sizeof(L_list));
if (L ->next == NULL)
{
L -> next = newNode;
tail = newNode;
tail -> data = data;
tail -> next = NULL;
}
else
{
newNode ->next = tail;
L->next = newNode;
newNode -> data = data;
tail = newNode;
}
}
return L;
}
#endif /* end of define TAIL */
void foreach(L_list * L) //遍历链表
{
if (NULL == L)
{
return ;
}
while (NULL != L->next)
{
L = L->next;
printf("%d\n", L->data);
}
}
L_list * insert_data(L_list* L, int pose, int data) //按位插入元素
{
if (NULL == L || pose < 0)
{
return;
}
int i = 0;
L_list* tmp;
L_list* l;
l= L;
tmp = L;
for ( i = 0; i<pose; i++)
{
tmp = l->next;
l = l->next;
}
L_list * newNode = malloc(sizeof(L_list));
newNode ->data = data;
newNode -> next = tmp ->next->next;
tmp ->next = newNode;
return L;
}
L_list * delete_data(L_list* L, int pose) //按位删除元素
{
if (NULL == L || pose < 0)
{
return;
}
L_list* tmp;
L_list* l;
l= L;
tmp = L;
int i = 0;
for (i = 0; i< pose; i++)
{
tmp = l->next;
l = l->next;
}
tmp = tmp ->next;
l->next = tmp -> next;
free(tmp);
return L;
}