链表是Linux内核中最简单、最普通的数据结构。链表是一种存放和操作可变数量元素的数据结构。链表和静态数组的不同之处在于,它所包含的元素都是动态创建并插入链表的,在编译时不必知道具体需要创建多少个元素。另外也因为链表中的每个元素的创建时间各不相同,所以它们在内存中无须占用连续内存区。正是因为元素不连续地存放,所以各元素需要通过某种方式被连接在一起。于是每个元素都包含一个指向下一个元素的指针,当有元素加入链表或从链表中删除元素时,简单调整指向下一个节点的指针就可以了。
这次使用的Makefile需要将各个文件连接,而且文件都不在一个目录下,现在我们来看一下这个目录树:
list/
├── header
│ └── list.h
├── source
│ └── list.c
└── user
└── Makefile
目的是在user文件下生成输出文件。
Makefile
HEADER_PATH = ../header/
SOURCE = ../source/list.c
HEADER = ../header/list.h
TARGET = list
TARGET:$(SOURCE) $(HEADER)
gcc -o $(TARGET) $(SOURCE) -I$(HEADER_PATH) -Wall
.PHONY:clean
clean:
rm -f $(TARGET)
list.h
#ifndef __LIST_H
#define __LIST_H
#include <stdio.h>
#include <malloc.h>
/**定义一个链表结构体**/
struct Node{
int data;
struct Node *next;
};
/**创建链表**/
struct Node *creat(int n)
{
int i,data;
struct Node *head,*p1,*p2; //head为链表的头,p1指向每次新分配的内存空间,p2总是用来指向尾节点且通过p2链入新分配的节点
head = NULL; //初始化链表头指针
for(i = 0; i < n; i++){
printf("请输入链表第%d个节点的值:",i+1);
scanf("%d",&data);
p1 = (struct Node*)malloc(sizeof(struct Node)); //分配地址
p1->data = data;
if(head == NULL){ //如果是创建的是第一个链表节点
head = p1; //作为头
p2 = p1; //p2准备链入下一个节点
} else {
p2->next = p1; //链入下一个节点
p2 = p1; //准备链入下一个节点
}
p2->next = NULL; //结束
}
return head;
}
struct Node *reverse(struct Node *head)
{
struct Node *p,*r;
if(head->next && head->next->next){ //链表长度在三个或以上才可以逆置
p = head;
r = p->next;
p->next = NULL;
while(r){
p = r;
r = r->next;
p->next = head;
head = p;
}
return head;
}
return head;
}
#endif
list.c
/************************************************
**创建单链表
************************************************/
#include "list.h"
int main(void)
{
int n;
struct Node *head,*current;
printf("输入你想创建的链表节点数\n");
scanf("%d",&n);
head = creat(n);
n = 0;
printf("----------显示创建的链表-------\n");
current = head;
while(current){
printf("第%d个链表节点数据:%d\n",++n,current->data);
current = current->next;
};
printf("----------逆置后的链表---------\n");
current = reverse(head);
n = 0;
while(current){
printf("第%d个链表节点数据:%d\n",++n,current->data);
current = current->next;
};
n = 0;
return 0;
}
2017-11-24-LR