单向链表
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 10
typedef int datatype;
typedef struct node
{
datatype data;
struct node *next;
}Mylist,*List;
List init()
{
List ne = (List)malloc(sizeof(Mylist));
if(ne == NULL)
{
printf("creat faile: %s\n",strerror(errno));
exit(1);
}
ne->next = NULL;
return ne;
}
void insert_list(List head, datatype num)
{
List ne = init();
ne->data = num;
List tmp = head;
while(tmp->next != NULL)
tmp = tmp->next;
ne->next = tmp->next;
tmp->next = ne;
}
void delete_list(List head, int indx)
{
List slow = head;
List fast = slow->next;
for(int i = 0; i <indx; i++)
{
slow = slow->next;
fast = fast->next;
}
slow->next = fast->next;
fast->next = NULL;
}
void display_list(List head)
{
List tmp = head->next;
while(tmp != NULL)
{
printf("%d ",tmp->data);
tmp = tmp->next;
}
printf("\n");
}
void fanzhuan_list(List head)
{
List p = head->next;
head->next = NULL;
List tmp;
while(p != NULL)
{
tmp = p->next;
p->next = head->next;
head->next = p;
p = tmp;
}
}
int main()
{
List phead = init();
datatype num;
while(1)
{
int flag = scanf("%d",&num);
if(flag != 1)
break;
insert_list(phead, num);
display_list(phead);
}
delete_list(phead,0);
display_list(phead);
fanzhuan_list(phead); //翻转链表
display_list(phead);
return 0;
}
双向循环链表
缺点:每一个节点都是特殊的,导致每一条链表也是特殊的,因此每一种链表的增删查改也是特殊的。所以针对不同数据要写不同的链表,代码不能复用。
当一个节点处于变化的数据结构网络中时,节点指针无法指向稳定不变的节点。
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 10
typedef int datatype;
typedef struct node
{
datatype data;
struct node *next, *prve;
}node, *mylist;
mylist init()
{
mylist ne = (mylist)malloc(sizeof(node));
if(ne == NULL)
{
printf("creat faile %s \n",strerror(errno));
exit(1);
}
ne->prve = ne->next = ne;
return ne;
}
mylist creat_list(int num)
{
mylist ne = (mylist)malloc(sizeof(node));
if(ne == NULL)
{
printf("creat faile %s \n",strerror(errno));
exit(2);
}
ne->data = num;
ne->next = ne->prve = NULL;
return ne;
}
void list_insert_tail(mylist head, mylist p)
{
p->prve = head->prve;
p->next = head;
head->prve->next = p;
head->prve = p;
}
void display_list(mylist head)
{
mylist tmp = head->next;
while(tmp != head)
{
printf("%d ",tmp->data);
tmp = tmp->next;
}
printf("\n");
}
void remove_list(mylist p)
{
p->prve->next = p->next;
p->next->prve = p->prve;
p->next = p->prve = NULL;
}
void rearrang_list(mylist head)
{
mylist p = head->prve;
mylist tmp;
bool flag = false; //当第一个数是偶数时,就不用进行移动操作了
while(p != head)
{
if(p->data % 2 == 0 && flag != false)
{
remove_list(p);
list_insert_tail(head, p);
p = tmp; //交换过后,将p指向上一次的奇数位置
}
else
{
tmp = p; //记录指针指向奇数时的位置
}
p = p->prve;
flag = true;
}
}
int main()
{
mylist head = init();
int num,i;
scanf("%d",&num);
for(i = 1; i <= num; i++)
{
mylist ne = creat_list(i);
list_insert_tail(head,ne);
}
display_list(head);
//实现将奇数放在前面,偶数放在后面
rearrang_list(head);
display_list(head);
return 0;
}
Linux内核链表
实现原理:将只有双向链表逻辑的小结构体,放入有具体数据的大结构体中
#include <stdio.h>
#include <stdlib.h>
#include <> //包含内核链表的文件
struct node
{
int data;
//只包含链表逻辑的“小结构体”
struct list_head list;
};
struct node *init_list()
{
struct node *head = malloc(sizeof(struct node));
INIT_LIST_HEAD(&head->list); //让小结构体的前后指针指向自己
return head;
}
struct node *new_node(int data)
{
struct node *ne = malloc(sizeof(struct node));
ne->data = data;
bzero(&ne->list, sizeof(struct list_head)); //将前后指针指向空
return ne;
}
void show(struct node *head)
{
struct list_head *pos;
struct node *p;
list_for_each(pos, &head->list)
{
p = list_entry(pos, struct node, list); //通过小结构体指针,找到大结构的指针
printf("%d ",p->data);
}
printf("\n");
}
void rearrange(struct node *head)
{
struct list_head *pos,*tmp;
struct node *p;
int flag = 0;
list_for_each(pos, &head->list)
{
p = list_entry(pos, struct node, list);
if(p->data % 2 == 0 && falg != 0)
{
list_move_tail(pos, &head->list); //将p指向的节点移到头节点之前
pos = tmp;
}
else
{
tmp = pos;
}
flag = 1;
}
}
int main()
{
struct node *head;
head = init_list();
int n;
scanf("%d",&n);
for(int i = 1; i < =n; i++)
{
struct node *ne = new_node(i);
list_add_tail(&ne->list, &head->list);
}
show(head);
rearrange(head);
show(head);
return 0;
}