双向循环链表的简单操作

    最近看了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;
}
这里只是一些简单的操作,如果要做成一个比较完善的系统,还有很多地方要修改,不过基本的功能基本上都实现。

posted on 2010-09-01 16:16  生活费  阅读(669)  评论(0编辑  收藏  举报

导航