最近看了linux内核代码list.h发现大部分都是链表的一些操作,所以就把双向循环链表的一些简单操作写了写,结果发现什么东西还是要经常练,不然就生疏了;主要实现了双向链表的增、删、改、查、排序、及双向遍历。
源码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
typedef struct student
{
int id;
char name[20];
struct student *pre,*next;
}stu,*linklist;
void init(linklist *head) //初始化头结点
{
(*head)=(linklist)malloc(sizeof(stu));
printf("please input the first student`s id:\n");
scanf("%d",&(*head)->id);
printf("please input the first student`s name:\n");
scanf("%s",(*head)->name);
(*head)->pre=*head;
(*head)->next=*head;
}
linklist del(linklist head,int id) //按学号删除一个节点
{
stu *p=head;
if (id == head->id)
{
printf("the entry you del is the head\n");
head->pre->next = head->next;
head->next->pre = head->pre;
head = head->next;
}
else
{
while (id != p->id)
p = p->next;
p->pre->next = p->next;
p->next->pre = p->pre;
}
free(p);
return head; //必须返回头节点,否则删除头结点后,不能正常遍历链表
}
void add_entry(linklist head) //头插法添加一个节点
{
stu *new;
new=(stu *)malloc(sizeof(stu));
printf("please input id\n");
scanf("%d",&new->id);
printf("please input name:\n");
scanf("%s",new->name);
new->next = head->next;
new->pre = head->next->pre;
head->next->pre = new;
head->next = new;
}
void add_entry_tail(linklist head) //尾插法添加一个节点
{
stu *new,*p = head;
new=(stu *)malloc(sizeof(stu));
printf("please input id\n");
scanf("%d",&new->id);
printf("please input name:\n");
scanf("%s",new->name);
while (p->next != head)
p = p->next;
new->next = head;
head->pre = new;
new->pre = p;
p->next = new;
}
int change(linklist head,int id) //修改学号为id的学生的信息
{
stu *p=head;
while (p->id != id)
{
p = p->next;
if (p == head)
{
printf("there is no student you want to change the info:\n");
return 0;
}
}
printf("please input new id and name:\n");
scanf("%d%s",&p->id,p->name);
return 1;
}
void swap(stu *p,stu *q) //交换p和q两个节点的数据,用于排序
{
int id1;
char name1[20];
id1=p->id;
p->id=q->id;
q->id=id1;
strcpy(name1,p->name);
strcpy(p->name,q->name);
strcpy(q->name,name1);
}
void sort_id(linklist head) //按学号排序
{
stu *p=head,*q;
while (p->next != head)
{
q = p->next;
while (q != head)
{
if((p->id) > (q->id))
swap(p,q);
q=q->next;
}
p=p->next;
}
}
int find_id(linklist head,int id) //按学号查找
{
stu *p=head;
while (p->id != id)
{
p = p->next;
if (p == head)
{
printf("no found the student\n");
return 0;
}
}
printf("\nthe info of the student is:\n");
printf("id is :%d\n",p->id);
printf("name is :%s\n",p->name);
return 1;
}
int find_name(linklist head,char name[]) //按姓名查找
{
stu *p=head;
int flag=0;
/*无重名情况下如下编写即可
while(strcmp(p->name,name)!=0)
{
p=p->next;
if(p==head)
{
printf("no found the student\n");
return 0;
}
}
printf("\nthe info of the student is:\n");
printf("id is :%d\n",p->id);
printf("name is :%s\n",p->name);
return 1; */
//为防止有重名情况不能将所有学生信息查到,如下处理
do
{
if (strcmp(p->name,name) == 0)
{
printf("\nthe info of the student is:\n");
printf("id is :%d\n",p->id);
printf("name is :%s\n",p->name);
flag=1;
}
p=p->next;
}while (p != head);
if(flag==0)
{
printf("no found the student\n");
return 0;
}
return 1;
}
void list_for_each(linklist head) //遍历每个节点并打印出信息,按next顺序
{
stu *p=head;
printf("************************************************\n");
do
{
printf("%d %s\n",p->id,p->name);
p = p->next;
}while (p != head);
}
void list_for_each_pre(linklist head) //遍历每个节点并打印出信息,按pre顺序
{
stu *p = head->pre,*q = head->pre;
printf("**************************************************\n");
do
{
printf("%d %s\n",p->id,p->name);
p = p->pre;
}while (p != q);
}
linklist add_entry_aftersort(linklist head) //排序后添加一个节点到合适的位置,使链表仍然按学号有序
{
stu *new,*p=head;
new=(stu *)malloc(sizeof(stu));
printf("add entry after sort----");
printf("please input id\n");
scanf("%d",&new->id);
printf("please input name:\n");
scanf("%s",new->name);
do
{
if ((new->id > p->id) && (new->id < p->next->id))
{
new->next = p->next;
new->pre = p;
p->next->pre = new;
p->next = new;
break;
}
p = p->next;
}while (p != head);
if (p == head)
{
new->next = p;
new->pre = p->pre;
p->pre->next = new;
p->pre = new;
if ((new->id) <= (head->id))
head = new;
}
return head;
}
int main()
{
linklist head;
int id;
char name[20];
init(&head);
add_entry(head);
add_entry(head);
add_entry_tail(head);
list_for_each(head);
printf("please input the id you want to del:\n");
scanf("%d",&id);
head=del(head,id);
list_for_each_pre(head);
printf("please input the id you want to change:\n");
scanf("%d",&id);
change(head,id);
list_for_each(head);
sort_id(head);
printf("\n顺序打印:\n");
list_for_each(head);
printf("\n逆序打印:\n");
list_for_each_pre(head);
head=add_entry_aftersort(head);
list_for_each(head);
printf("please input the id you want to search:\n");
scanf("%d",&id);
find_id(head,id);
printf("please input the name you want to search:\n");
scanf("%s",name);
find_name(head,name);
return 0;
}
这里只是一些简单的操作,如果要做成一个比较完善的系统,还有很多地方要修改,不过基本的功能基本上都实现。