数据结构——链表的操作

来源:互联网 发布:瓷砖设计软件手机版 编辑:程序博客网 时间:2024/05/21 13:23

这两天上课正好做到关于链表的一些操作,所以就把自己写的一些东西记录下来了

代码如下,不足之处望大家指正,旨在共同学习进步O(∩_∩)O~

#include <stdio.h>#include <stdlib.h>#include <time.h>//定义链表的结构体typedef struct node{int data;struct node *next;}node;//遍历输出链表void print(node *s){//利用一个中间节点来遍历链表并输出node *temp;temp=s->next;while(temp!=NULL){printf("%d ",temp->data);temp=temp->next;}printf("\n");}//查找元素void find(node *s,int destination){//利用一个中间节点来遍历链表并输出node *temp;temp=s->next;while(temp!=NULL){if(temp->data==destination){printf("存在该元素!\n");return;}temp=temp->next;}    printf("不存在该元素!\n");printf("\n");}//插入节点node *add(node *s,int number){node *temp_list;for(int i=0;i<number;i++){if(temp_list==NULL){printf("error!\n");exit(1);}temp_list=(node *)malloc(sizeof(node));temp_list->data=rand()%100+1;temp_list->next=s->next;s->next=temp_list;}return s;}//删除节点node *del(node *s,int number){node *temp;for(int i=0;i<number;i++){//保存头结点指针域temp=s->next;//删除节点s->next=(s->next)->next;temp->next=NULL;//(s->next)->next=NULL;//s=s->next;}return s;}int main(void){//创建头结点node *head;node *list;srand(time(0));head=(node *)malloc(sizeof(node));//错误处理if(head==NULL)exit(1);head->next=NULL;//创建链表(头插法)list=(node *)malloc(sizeof(node));head->next=list;list->data=rand()%100+1;list->next=NULL;for(int i=0;i<9;i++){//错误处理if(list==NULL){printf("error!\n");exit(1);}list=(node *)malloc(sizeof(node));list->data=rand()%100+1;list->next=head->next;head->next=list;}print(head);////////////////////////////////////////////int operate;printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");while(scanf("%d",&operate)==1){switch(operate){case 1:{       int add_number;   printf("请输入要插入节点的个数:");   scanf("%d",&add_number);   head=add(head,add_number);   print(head);   };break;case 2:{       int delete_number;   printf("请输入要删除的节点个数:");   scanf("%d",&delete_number);   head=del(head,delete_number);   print(head);   };break;case 3:{       int number;   printf("请输入要查找的元素:");   scanf("%d",&number);   find(head,number);   };break;default:exit(1);}printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");}free(head);free(list);return 0;}

以下是调试的结果(这里我用的都是随机的方法生成的数字):


继续上次的实验内容

这一次是添加了一个排序的功能(将两个链表合并之后进行升序的排列)

#include <stdio.h>#include <stdlib.h>#include <time.h>#define SWAP(a,b,c) ((c)=(a),(a)=(b),(b)=(c))//定义链表的结构体typedef struct node{int data;struct node *next;}node;void print(node *s){node *m;m=s->next;while(m!=NULL){printf("%-2d ",m->data);m=m->next;}printf("\n");}int main(void){//创建两个链表node *head1;node *head2;node *list1;node *list2;//创建表1head1=(node *)malloc(sizeof(node));head1->next=NULL;list1=(node *)malloc(sizeof(node));srand(time(0));list1->data=rand()%100+1;head1->next=list1;list1->next=NULL;for(int i=0;i<9;i++){list1=(node *)malloc(sizeof(node));    list1->data=rand()%100+1;list1->next=head1->next;    head1->next=list1;}printf("表1内容:\n");print(head1);////////////////////////////////////////////////////////创建表2head2=(node *)malloc(sizeof(node));list2=(node *)malloc(sizeof(node));list2->data=rand()%100+1;head2->next=list2;list2->next=NULL;for(int j=0;j<9;j++){list2=(node *)malloc(sizeof(node));    list2->data=rand()%100+1;list2->next=head2->next;    head2->next=list2;}printf("表2内容:\n");print(head2);/////////////////////////////////////////////////////////合并两个链表node *head3;head3=head1->next;while(head3!=NULL){if(head3->next==NULL){head3->next=head2->next;break;}head3=head3->next;}printf("合并之后的内容:\n");print(head1);/////////////////////////////////////////////////////////排序(选择排序)int temp;node *m=head1->next;node *n=NULL;while(m!=NULL){n=m->next;while(n!=NULL){if(m->data>n->data)    SWAP(m->data,n->data,temp);n=n->next;}m=m->next;//n=m->next;}printf("排序之后的内容:\n");print(head1);///////////////////////////////////////////////////////free(head1);free(head2);free(head3);free(list1);free(list2);        free(m);        free(n);return 0;}


下面的运行结果(节点数我是一次性设置了十个,也可以自己修改一下,做一个任意设置的,数字也是随机生成的):


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

上面用的是头插法产生的链表,再输出的时候会差生一个问题(手动输入数据的话),就是反着输出来

所以现在用尾插法来修改一下,并且对之前不能在任意位置进行插入和删除节点也做了修改,具体的代码如下(新添加一个链表就地逆置的函数):

#include <stdio.h>  #include <stdlib.h>    int length;//链表的长度    typedef struct node{      int data;      struct node *next;  }node;    #define SWAP(a,b,c) ((c)=(a),(a)=(b),(b)=(c))  //////////////////////////////////////    //创建链表(尾插法)  node *create(node *s){      node *list,*p,*q;      p=s;      printf("请输入要建立的链表的长度:");      while(scanf("%d",&length)!=1);      printf("请依次输入链表元素:\n");      list=(node *)malloc(sizeof(node));      p->next=list;      scanf("%d",&list->data);      list->next=NULL;      for(int i=0;i<length-1;i++){          //临时节点          q=list;          //申请新的节点          list=(node *)malloc(sizeof(node));          scanf("%d",&list->data);          //前驱的指针域指向新的节点          q->next=list;          //新节点的指针域置空          list->next=NULL;          //list=q;      }      return s;  }  ////////////////////////////////////////    //打印链表  void print(node *s){      node *p;      p=s->next;      while(NULL!=p){          printf("%-3d",p->data);          p=p->next;      }      printf("\n");  }  ////////////////////////////////////////    //链表排序  void sort(node *s){      node *p,*q;      p=s;      int temp;      while(NULL!=p){          q=p->next;          while(NULL!=q){              if(p->data>q->data)                  SWAP(p->data,q->data,temp);              q=q->next;          }          p=p->next;      }  }  ////////////////////////////////////////    //插入元素  node *insertion(node *s){      int number,pos;      node *p;//记录插入位置的前驱      node *temp;//新插入的节点      p=s;      temp=(node *)malloc(sizeof(node));      printf("请输入要进行插入的位置:");      //输入并做错误处理      while(scanf("%d",&pos)==1&&pos>=1&&pos<=length){          for(int i=1;i<pos;i++)              p=p->next;          printf("请输入插入的值:\n");          while(scanf("%d",&number)!=1);          temp->data=number;          temp->next=p->next;          p->next=temp;          break;      }      length++;//插入之后,链表长度加1      return s;  }  ////////////////////////////////////////    //删除元素  node *_delete(node *s){      int pos;      node *p,*q;      p=s;      printf("请输入要删除的位置:");      //错误处理      while(scanf("%d",&pos)!=1&&pos>length);      for(int i=1;i<pos;i++){          //存储前驱          p=p->next;      }      //存下删除的位置      q=p->next;      p->next=q->next;      length--;//链表长度减1      return s;  }  ////////////////////////////////////////    //查找元素  void search(node *s){      int number;      node *temp=s->next;      printf("请输入要查找的元素:");      while(scanf("%d",&number)!=1);      while(NULL!=temp){          if(number==temp->data){              printf("存在该元素!\n");              return;          }          temp=temp->next;      }      printf("不存在该元素!\n");      return ;  }  ////////////////////////////////////////  //就地逆序置换链表的函数  void transport(node *list)  {      node *p,*q,*s;      //头指针不为空则进行置换      if(NULL != list)      {          //记录下首元素的节点和第二个节点          p = list->next;          q = p->next;          //头指针置空          list->next = NULL;          //首元素置空,起始端做终点端          p->next = NULL;          while(q)          {              //暂存下一个节点              s = q->next;              //next域逆置              q->next = p;              //指针后移              p = q;              q = s;           }          list->next = p;      }  }  ////////////////////////////////////////  //销毁链表  void destory(node *s){      node *temp;      node *q;      temp=s->next;      while(NULL!=temp){          //存储下一个节点          q=temp->next;          //释放当前节点          free(temp);//节点后移一位        temp=q;      }  }  ////////////////////////////////////////    int main(void){      node *head;      head=(node *)malloc(sizeof(node));      head->next=NULL;      //创建链表      head=create(head);      print(head);      /////////////////////////////////////      //链表排序      int temp;      printf("是否进行排序(1.是,2.否):");      scanf("%d",&temp);      if(1==temp){          printf("排序之后如下所示:\n");          sort(head);          print(head);      }      /////////////////////////////////////      int position;      printf("请输入要进行的操作(1.插入,2.删除,3.查找,4.逆序置换,5.退出):");      while(scanf("%d",&position)==1){          switch(position){          case 1:head=insertion(head);print(head);break;          case 2:head=_delete(head);print(head);break;          case 3:search(head);break;          case 4:transport(head);print(head);break;          default:exit(0);          }          printf("请输入要进行的操作(1.插入,2.删除,3.查找,4.逆序置换,5.退出):");      }      /////////////////////////////////////////////////////      //销毁链表      destory(head);  free(head);    return 0;  }  



运行结果截图:




---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

继续更新,这次是循环链表的操作,一个是建立一个循环链表,然后求出循环链表的长度(这里没有手动输入,手动输入的话稍微修改一下就行了),还有在首元素的节点之后插入一个新的节点的操作,代码如下:

#include <stdio.h>#include <stdlib.h>typedef struct node {int data;struct node *next;}node;void print(node *s){node *temp = s->next;do{printf("%-3d",temp->data);temp=temp->next;}while(s->next != temp);}//求循环链表的长度int f(node *s){int count = 0;node *temp = s->next;do{count ++;temp = temp->next;}while(s->next != temp);return count;}//表头插入节点void insert(node *s){int a;node *temp = s->next;node *insertion;insertion = (node *)malloc(sizeof(node));printf("请输入插入的元素:");scanf("%d",&a);insertion->data = a;insertion->next = temp->next;temp->next = insertion;}void destory(node *s){node *p = s->next,*q;//循环链表的终止条件要注意while(s->next != p){q = p->next;free(p);p = q;}}int main(int argc,char *args[]){node *head,*list,*p;head = (node *)malloc(sizeof(node));head->next = NULL;list = (node *)malloc(sizeof(node));head->next = list;list->data = 1;list->next = NULL;p = list;for(int i=1;i<=9;i++){list = (node *)malloc(sizeof(node));list->data = i+1;//链接新的节点p->next = list;list->next = NULL;//存储新节点作为下一节点的前驱p = list;}//终端端点链接首节点list->next = head->next;print(head);printf("\nThe length of the node table is:%d\n",f(head));insert(head);print(head);printf("\nThe length of the node table is:%d\n",f(head));destory(head);free(head);return 0;}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

课余时间继续更新,这次更新的是双向循环链表的相关操作(包括插入,删除,查找,以及创建一个和销毁一个双向循环链表的操作),由于双向循环链表的独特结构,所以在插入和删除操作的时间复杂度上都能达到常量级别,并且每个节点还有一个指针域指向自己的前驱,所以查找的话效率也会增加一些的,具体代码实现如下:

#include <stdio.h>#include <stdlib.h>typedef struct node {struct node *llink;int data;struct node *rlink;}node;void create(node *s){node *list,*temp;list = (node *)malloc(sizeof(node));list->data = 1;s->llink = NULL;s->rlink = list;list->rlink = NULL;for(int i = 2;i <= 10;i ++){//暂存一个节点temp = list;list = (node *)malloc(sizeof(node));list->data = i;list->llink = temp;temp->rlink = list;list->rlink = NULL;}list->rlink = s;s->llink = list;}void print(node *s){node *temp = s->rlink;while(s != temp){printf("%-3d",temp->data);temp = temp->rlink;}printf("\n");}void destory(node *s){node *p = s->rlink,*q = p->rlink;while(s != q){free(p);p = q;//暂存下一个节点q= q->rlink;}}void insert(node *s){int number;node *temp = s->rlink;node *newnode;newnode = (node *)malloc(sizeof(node));printf("请输入要插入的元素值:");while(scanf("%d",&number) != 1);newnode->data = number;newnode->rlink = temp->rlink;newnode->llink = temp;temp->rlink->llink = newnode;temp->rlink = newnode;}void del(node *s){node *temp = s->rlink;s->rlink = temp->rlink;s->rlink->llink = NULL;free(temp);}void search(node *s){int number;printf("请输入要查找的元素值:");while(scanf("%d",&number) != 1);node *temp = s->rlink;node *p = s->llink;//从双向链表的两端开始进行搜索while(p != temp){if(number == temp->data||number == p->data){printf("found!\n");return;}temp = temp->rlink;p = p->llink;}if(number == temp->data||number == p->data){printf("found!\n");return;}printf("not found!\n");}int main(int argc,char *args[]){node *head;head = (node *)malloc(sizeof(node));create(head);print(head);int pos;printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");while(scanf("%d",&pos) == 1){switch(pos){case 1:insert(head);print(head);break;case 2:del(head);print(head);break;case 3:search(head);print(head);break;default:exit(0);}printf("请输入要执行的操作(1.插入,2.删除,3.查找,4.退出):");}destory(head);free(head);return 0;}

下面是调试的结果截图:


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

有不足之处望大家指正,如果大家还有什么好的想法也可以提出来~~~