• 线性表之二,SLINKLIST(单链表)类,模板类及C链表(增删改查,广义表


    一、SLINKLIST(单链表)类,模板类

      1 /*
      2     该文件按习惯可以分成.h文件和实现的.cpp文件
      3  */
      4 template <class elemType>
      5 class sLinkList
      6 {
      7 private:
      8     struct node{ //定义单链表中的结点结构
      9         elemType data;
     10         node *next;
     11 
     12         node(const elemType &x, node *n = NULL)
     13         {
     14             data = x; next = n;;
     15         }
     16         node() :next(NULL) {}
     17         ~node() {}
     18     };
     19     
     20     node  *head;//头指针
     21     int currentLength;//表长
     22 
     23     //node *move(int i)const;//返回第i个结点的地址
     24     node *move(int i)const
     25     {
     26         node *p = head;
     27         while( i-- >= 0 )
     28         {
     29             p = p->next;
     30         }
     31         return p;
     32     } 
     33 
     34 public:
     35     sLinkList();
     36     ~sLinkList() {
     37         clear(); delete head;
     38     }
     39 
     40     void clear();
     41     int length()const {
     42         return currentLength;
     43     }
     44     void insert(int i, const elemType&x);
     45     void remove(int i);
     46     int search(const elemType&x)const;
     47     elemType visit(int i)const;
     48     void traverse()const;
     49 };
     50 
     51 // sLinkList
     52 template <class elemType>
     53 sLinkList<elemType> ::sLinkList()
     54 {
     55     head = new node;
     56     currentLength = 0;
     57 }
     58 
     59 // clear
     60 template <class elemType>
     61 void sLinkList<elemType> ::clear()
     62 {
     63     node *p = head->next, *q;
     64     head->next = NULL;
     65     while(p!=NULL)
     66     {
     67         q = p->next;
     68         delete p;
     69         p = q;
     70     }
     71     currentLength = 0;
     72 }
     73 
     74 // insert
     75 template <class elemType>
     76 void sLinkList<elemType> ::insert(int i, const elemType&x)
     77 {
     78     node *pos;
     79     pos = move(i-1);
     80     pos->next = new node(x, pos->next);
     81     ++currentLength;
     82 }
     83 
     84 /* // 类外实现,编译器编译不过,只好类内实现
     85 // move
     86 template <class elemType>
     87 sLinkList<elemType>::node *sLinkList<elemType> :: move(int i)const
     88 {
     89     node *p = head;
     90     while( i-- >= 0 )
     91     {
     92         p = p->next;
     93     }
     94     return p;
     95 }  */
     96 
     97 // search
     98 template <class elemType>
     99 int sLinkList<elemType> :: search(const elemType&x)const
    100 {
    101     node *p = head->next;
    102     int i=0;
    103     while( p != NULL && p->data != x )
    104     {
    105         p = p->next;
    106         ++i;
    107     }
    108     
    109     if(p == NULL)
    110         return -1;
    111     else
    112         return i;
    113 }    
    114 
    115 // visit
    116 template <class elemType>
    117 elemType sLinkList<elemType> :: visit(int i)const
    118 {
    119     return move(i)->data;
    120 }    
    121 
    122 // traverse
    123 template <class elemType>
    124 void sLinkList<elemType> :: traverse()const
    125 {
    126     node *p = head->next;
    127     cout<<endl;
    128     
    129     while( p != NULL )
    130     {
    131         cout<<p->data<<" ";
    132         p = p->next;
    133     }
    134     
    135     cout<<endl;
    136 }    
    137 
    138 // remove
    139 template <class elemType>
    140 void sLinkList<elemType> :: remove(int i)
    141 {
    142     node *pos, *delp;
    143     pos = move(i-1);
    144     delp = pos->next;
    145     
    146     pos->next = delp->next;
    147     delete delp;
    148     
    149     --currentLength;
    150 }
    sLinkList模板类(单链表代码)

    二、C语言链表(增删改查)

    1.删除一个元素,删除所有相同元素:

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <conio.h>
      4 
      5 /*定义结构体*/
      6 struct student
      7 {
      8     int num;
      9     float score;
     10     struct student *next;
     11 };
     12 
     13 /*创建一个只有头结点的空链表*/
     14 struct student *create_head()
     15 {
     16     struct student *head;
     17     head=(struct student*)malloc(sizeof (struct student) );
     18     if(head==NULL)      //小心别漏这个
     19     {
     20         printf("申请头结点失败!
    ");
     21         return NULL;
     22     }
     23     head->next=NULL;
     24     return head;
     25 }
     26 /*将s指向的结点插入链表,使链表保持升序,并返回头结点*/
     27 struct student *insert(struct student *head,struct student *s)
     28 {
     29     struct student *p=head;
     30     while(p->next!=NULL&&s->score>p->next->score){
     31     //特别注意&&左右不能写反,若s最大,最后p->next=NULL,p->next->score运行出错
     32         p=p->next;
     33     }
     34     if(p->next==NULL) //s->score最大的情况//其实两种情况可以并在一块写
     35     {
     36         p->next=s;    //连接结点
     37         s->next=NULL;   //p->next就等于NULL
     38     }
     39     else  //连接结点
     40     {
     41         s->next=p->next;
     42         p->next=s;    
     43     }
     44     return head ;
     45 }
     46 /*查找符合条件的结点,并返回指向该结点的指针*/
     47 struct student *search(struct student *head)
     48 {
     49     struct student *p=head->next;
     50     int num;
     51     printf("请输入要查找学生的学号:
    ");
     52     scanf("%d",&num);
     53     while(p!=NULL&&p->num!=num){
     54     //特别注意两条件不能写反,若写反最后p指向NULL时p->num找不到 运行出错
     55         p=p->next;
     56     }
     57     if(p==NULL)
     58     {
     59     //特别注意两个if不能调换,若调换最后p指向NULL时p->num运行出错
     60         printf("找不到符合条件的结点!!!");
     61     }
     62     else //if(p->num==num) 
     63     {
     64         printf("找到符合条件的结点
    该结点为%d	%f",p->num,p->score);
     65     }
     66     return p; //返回空指针或查找到的指针
     67 }
     68 /*输出链表各结点的值,也称对链表的遍历*/
     69 void print(struct student *head)
     70 {
     71     struct student *p;
     72     p=head->next;
     73 
     74     printf("  链表如下:  
    ");
     75     while(p!=NULL)
     76     {
     77         printf("%d	%.1f
    ",p->num,p->score);
     78         p=p->next;
     79     }
     80 }
     81 
     82 /*释放链表*/
     83 void free_list(struct student *head)
     84 {
     85     struct student *p=head ;
     86     printf("释放链表:
    ");
     87     while(p!=NULL)
     88     {
     89         head=head->next;
     90         free(p);
     91         p=head;
     92     }
     93     printf("释放链表成功!
    ");
     94 }
     95 /*删除链表中值为num的结点,并返回链表的首指针*/
     96 struct student *delete_node(struct student *head,int num_x)
     97 {
     98     struct student *p1=head->next , *p2=head ;
     99     while(p1!=NULL&&p1->num!=num_x)
    100     {//特别注意&&左右条件不能调换,若调换如果p1指向NULL时p1->num运行出错
    101         p2=p1;
    102         p1=p1->next;
    103     }
    104     if(p1==NULL)
    105     {
    106         //特别注意两个if不能调换,若调换如果p1指向NULL时,p1->num运行出错
    107         printf("找不到符合删除要求的结点!!!
    ");
    108     }
    109     else //if(p1->num==num_x)
    110     {
    111         p2->next=p1->next;
    112         free(p1);
    113         printf("结点删除成功!
    ");
    114     }
    115     return head;
    116 }
    117 
    118 /*完整的有头结点链表操作程序*/
    119 int main()
    120 {
    121     struct student *p , *head ;
    122     char c;
    123     int num ;
    124     float score ;
    125     printf("有头结点链表操作程序:
    ");
    126     head=create_head();
    127     while(1)
    128     {
    129         printf("I:插入结点(自动升序)  P:输出链表 
    130                S:查找结点  D:删除结点  E:释放链表并退出程序!  ");
    131         c=getch();
    132         switch(c)
    133         {
    134             case'I':
    135                 printf("请分别输入要插入学生的学号和分数:
    ");
    136                 scanf("%d%f",&num,&score);
    137                 p=(struct student*)malloc( sizeof(struct student) );
    138                 if(p==NULL)
    139                 {
    140                     printf("申请该结点失败!!!
    ");
    141                     exit (0) ;
    142                 }
    143                 p->num=num;  p->score=score;   //给p赋值
    144                 insert(head,p);
    145                 printf("插入成功!
    ");
    146                 break;
    147             case'P':
    148                 print(head);
    149                 break;
    150             case'S':
    151                 search(head);
    152                 break;
    153             case'D':
    154                 printf("请输入要删除的学生的学号:
    ");
    155                 scanf("%d",&num);
    156                 delete_node(head,num);
    157                 break;
    158             case'E':
    159                 free_list(head);
    160                 exit (0);
    161         }
    162     }
    163     return 0;
    164 }
    增删改查
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <conio.h>
      4 
      5 /*定义结构体*/
      6 struct node{
      7     int num;
      8     struct node *next;
      9 };
     10 
     11 /*创建一个只有头结点的空链表*/
     12 struct node *create_head()
     13 {
     14     struct node *head;
     15     head = (struct node*)malloc(sizeof (struct node) );
     16     
     17     if(head == NULL)   //小心别漏这个
     18     {
     19         printf("申请头结点失败!
    ");
     20         return NULL;
     21     }
     22     head->next = NULL;
     23     return head;
     24 }
     25 
     26 /*将s指向的结点插入链表,使链表保持升序,并返回头结点*/
     27 struct node *insert(struct node *head,int num)
     28 {    
     29     struct node *p = head, *s;
     30     s = (struct node*)malloc( sizeof(struct node) );
     31     if(s == NULL)
     32     {
     33         printf("申请该结点失败!!!
    ");
     34         exit (0) ;
     35     }
     36     s->num = num; //给p赋值
     37     
     38     while(p->next != NULL && s->num >= p->next->num){
     39     //特别注意&&左右不能写反,若s最大,最后p->next=NULL,p->next->num运行出错
     40         p = p->next;
     41     }
     42    
     43     s->next = p->next; //若s最大, p->next=NULL
     44     p->next = s;   
     45     printf("插入成功!
    ");
     46     
     47     return head ;
     48 }
     49 
     50 /*输出链表各结点的值,也称对链表的遍历*/
     51 void print(struct node *head)
     52 {
     53     struct node *p;
     54     p = head->next;
     55     
     56     if(!p){
     57         printf("链表为空
    ");
     58         return;
     59     }
     60 
     61     printf("链表如下:  
    ");
     62     while(p!=NULL)
     63     {
     64         printf("%d	",p->num);
     65         p = p->next;
     66     }
     67     printf("
    ");
     68 }
     69 
     70 /* 删除链表所有值为num的结点 */
     71 struct node *delete_num(struct node *head,int num)
     72 {
     73     int flag = 1;
     74     struct node *p1 = head->next , *p2 = head ;
     75     if(p1 == NULL){
     76         printf("链表为空
    ");
     77         return head;
     78     }
     79     
     80     while(p1 != NULL){ 
     81         if(p1->num == num){    //找到,删除
     82             p2->next = p1->next; //链接后续元素
     83             free(p1); // 删除元素
     84             printf("结点删除成功!
    ");
     85             flag = 0;
     86             p1 = p2->next;    //p1指向后续元素        
     87         }
     88         else{    //没找到,指针后移    
     89             p2 = p1; //保持p2在p1前面
     90             p1 = p1->next; //指针后移
     91         }       
     92     }
     93     
     94     if(flag){
     95         printf("找不到符合删除要求的结点!!!
    ");
     96     }
     97         
     98     return head;
     99 }
    100 
    101 int main()
    102 {
    103     struct node *head ;
    104     char c;  
    105     int num ;
    106     printf("有头结点链表操作程序:
    ");
    107     head = create_head();
    108     
    109     while(1)
    110     {
    111         printf("i:插入结点(自动升序) p:输出链表 d:删除结点 e:退出 
    ");
    112         c = getch();
    113         switch(c)
    114         {
    115             case'i':
    116                 printf("请输入要插入的数据:
    ");
    117                 scanf("%d",&num);          
    118                 insert(head,num);
    119                 break;
    120             case'p':
    121                 print(head);
    122                 break;           
    123             case'd':               
    124                 printf("请输入要删除结点的数据:
    ");
    125                 scanf("%d",&num);
    126                 delete_num(head,num);                
    127                 break; 
    128             case'e':  
    129                 exit (0) ;
    130         }
    131     }
    132     return 0;
    133 }
    删除所有值为num的结点

    2. 删除一个或多个元素,使用函数指针

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <conio.h>
      4 
      5 /*定义结构体*/
      6 struct node{
      7     int num;
      8     struct node *next;
      9 };
     10 
     11 /*创建一个只有头结点的空链表*/
     12 struct node *create_head()
     13 {
     14     struct node *head;
     15     head = (struct node*)malloc(sizeof (struct node) );
     16     
     17     if(head == NULL)   //小心别漏这个
     18     {
     19         printf("申请头结点失败!
    ");
     20         return NULL;
     21     }
     22     head->next = NULL;
     23     return head;
     24 }
     25 
     26 /*将s指向的结点插入链表,使链表保持升序,并返回头结点*/
     27 struct node *insert(struct node *head,int num)
     28 {    
     29     struct node *p = head, *s;
     30     s = (struct node*)malloc( sizeof(struct node) );
     31     if(s == NULL)
     32     {
     33         printf("申请该结点失败!!!
    ");
     34         exit (0) ;
     35     }
     36     s->num = num; //给p赋值
     37     
     38     while(p->next != NULL && s->num >= p->next->num){
     39     //特别注意&&左右不能写反,若s最大,最后p->next=NULL,p->next->num运行出错
     40         p = p->next;
     41     }
     42    
     43     s->next = p->next; //若s最大, p->next=NULL
     44     p->next = s;   
     45     printf("插入成功!
    ");
     46     
     47     return head ;
     48 }
     49 
     50 /*输出链表各结点的值,也称对链表的遍历*/
     51 void print(struct node *head)
     52 {
     53     struct node *p;
     54     p = head->next;
     55     
     56     if(!p){
     57         printf("链表为空
    ");
     58         return;
     59     }
     60 
     61     printf("链表如下:  
    ");
     62     while(p!=NULL)
     63     {
     64         printf("%d	",p->num);
     65         p = p->next;
     66     }
     67     printf("
    ");
     68 }
     69 
     70 /* 删除元素 */
     71 struct node *delete_num(struct node *head,int (*del)(int a,int b,int c),int num1, int num2=0)
     72 {
     73     int flag = 1;
     74     struct node *p1 = head->next , *p2 = head ;
     75     if(p1 == NULL){
     76         printf("链表为空
    ");
     77         return head;
     78     }
     79     
     80     while(p1 != NULL){ 
     81         if(del(p1->num,num1,num2)){    //找到,删除
     82             p2->next = p1->next; //链接后续元素
     83             free(p1); // 删除元素
     84             printf("结点删除成功!
    ");
     85             flag = 0;
     86             p1 = p2->next;    //p1指向后续元素        
     87         }
     88         else{    //没找到,指针后移    
     89             p2 = p1; //保持p2在p1前面
     90             p1 = p1->next; //指针后移
     91         }       
     92     }
     93     
     94     if(flag){
     95         printf("找不到符合删除要求的结点!!!
    ");
     96     }
     97         
     98     return head;
     99 }
    100 
    101 //删除一个或多个
    102 int del(int a,int b,int c){
    103     if(c==0){
    104         return a==b;
    105     }
    106     return a>=b && a<=c;
    107 }
    108 
    109 int main()
    110 {
    111     struct node *head ;
    112     char c,c1;  
    113     int num1, num2 ;
    114     printf("有头结点链表操作程序:
    ");
    115     head = create_head();
    116     
    117     while(1)
    118     {
    119         printf("i:插入结点(自动升序) p:输出链表 d:删除结点 e:退出 
    ");
    120         c = getch();
    121         switch(c)
    122         {
    123             case'i':
    124                 printf("请输入要插入的数据:
    ");
    125                 scanf("%d",&num1);          
    126                 insert(head,num1);
    127                 break;
    128             case'p':
    129                 print(head);
    130                 break;           
    131             case'd':
    132                 printf("1:删除一个结点 2:删除结点(范围)
    ");
    133                 c1 = getch(); //不回显
    134                 switch(c1){
    135                     case '1':
    136                         printf("请输入要删除的结点:
    ");
    137                         scanf("%d",&num1);
    138                         delete_num(head,del,num1); 
    139                         break;
    140                     case '2':
    141                         printf("请输入要删除结点值的范围:
    ");
    142                         scanf("%d%d",&num1,&num2);
    143                         delete_num(head,del,num1,num2);  
    144                         break;
    145                 }                  
    146                 break; 
    147             case'e':  
    148                 exit (0) ;
    149         }
    150     }
    151     return 0;
    152 }
    删除一个或多个
    3. 链表,删除给定值S与T之间的所有元素
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <conio.h>
      4 
      5 /*定义结构体*/
      6 struct node{
      7     int num;
      8     struct node *next;
      9 };
     10 
     11 /*创建一个只有头结点的空链表*/
     12 struct node *create_head()
     13 {
     14     struct node *head;
     15     head = (struct node*)malloc(sizeof (struct node) );
     16     
     17     if(head == NULL)   //小心别漏这个
     18     {
     19         printf("申请头结点失败!
    ");
     20         return NULL;
     21     }
     22     head->next = NULL;
     23     return head;
     24 }
     25 
     26 /*将s指向的结点插入链表,使链表保持升序,并返回头结点*/
     27 struct node *insert(struct node *head,int num)
     28 {    
     29     struct node *p = head, *s;
     30     s = (struct node*)malloc( sizeof(struct node) );
     31     if(s == NULL)
     32     {
     33         printf("申请该结点失败!!!
    ");
     34         exit (0) ;
     35     }
     36     s->num = num; //给p赋值
     37     
     38     while(p->next != NULL && s->num >= p->next->num){
     39     //特别注意&&左右不能写反,若s最大,最后p->next=NULL,p->next->num运行出错
     40         p = p->next;
     41     }
     42    
     43     s->next = p->next; //若s最大, p->next=NULL
     44     p->next = s;   
     45     printf("插入成功!
    ");
     46     
     47     return head ;
     48 }
     49 
     50 /*输出链表各结点的值,也称对链表的遍历*/
     51 void print(struct node *head)
     52 {
     53     struct node *p;
     54     p = head->next;
     55     
     56     if(!p){
     57         printf("链表为空
    ");
     58         return;
     59     }
     60 
     61     printf("链表如下:  
    ");
     62     while(p!=NULL)
     63     {
     64         printf("%d	",p->num);
     65         p = p->next;
     66     }
     67     printf("
    ");
     68 }
     69 
     70 /* 删除给定值num1与num2之间的所有元素 */
     71 struct node *delete_num(struct node *head,int num1, int num2)
     72 {
     73     int flag = 1;
     74     struct node *p1 = head->next , *p2 = head ;
     75     if(p1 == NULL){
     76         printf("链表为空
    ");
     77         return head;
     78     }
     79     
     80     while(p1 != NULL){ 
     81         if(p1->num >= num1 && p1->num <=num2){    //找到,删除
     82             p2->next = p1->next; //链接后续元素
     83             free(p1); // 删除元素
     84             printf("结点删除成功!
    ");
     85             flag = 0;
     86             p1 = p2->next;    //p1指向后续元素        
     87         }
     88         else{    //没找到,指针后移    
     89             p2 = p1; //保持p2在p1前面
     90             p1 = p1->next; //指针后移
     91         }       
     92     }
     93     
     94     if(flag){
     95         printf("找不到符合删除要求的结点!!!
    ");
     96     }
     97         
     98     return head;
     99 }
    100 
    101 int main()
    102 {
    103     struct node *head ;
    104     char c;  
    105     int num1, num2 ;
    106     printf("有头结点链表操作程序:
    ");
    107     head = create_head();
    108     
    109     while(1)
    110     {
    111         printf("i:插入结点(自动升序) p:输出链表 d:删除结点(范围) e:退出 
    ");
    112         c = getch();
    113         switch(c)
    114         {
    115             case'i':
    116                 printf("请输入要插入的数据:
    ");
    117                 scanf("%d",&num1);          
    118                 insert(head,num1);
    119                 break;
    120             case'p':
    121                 print(head);
    122                 break;           
    123             case'd':               
    124                 printf("请输入要删除结点值的范围:
    ");
    125                 scanf("%d%d",&num1,&num2);
    126                 delete_num(head,num1,num2);                
    127                 break; 
    128             case'e':  
    129                 exit (0) ;
    130         }
    131     }
    132     return 0;
    133 }
    链表,删除区间元素
    4、链表逆序
      1 #include <stdio.h>
      2 #include <malloc.h>
      3 
      4 /* 定义链表结点 */
      5 typedef struct node NODE;
      6 typedef struct node* Linklist;
      7 struct node{
      8     int data;
      9     Linklist next;
     10 };
     11 
     12 /* 逆序链表 */
     13 Linklist reverse(Linklist L, Linklist next)
     14 {
     15     if(next == NULL)
     16         return L;
     17     Linklist head = reverse(L->next, next->next);//一直压栈
     18     next->next = L;//退栈逆序(前驱成后继)
     19     L->next = NULL;  //保证逆序前的第一个结点的next为NULL
     20     return head;//传递逆序前的最后一个结点的指针
     21 } 
     22 void reverse(Linklist L)//包装逆序函数
     23 {
     24     if(L == NULL || L->next == NULL)
     25         return; //指针为空或链表为空
     26     L->next = reverse(L->next, L->next->next);
     27 } 
     28 
     29 /* 
     30 //利用前后三个指针逐个结点逆序
     31 void reverse(Linklist L)
     32 {
     33     Linklist NEW = NULL, CUR = L->next, TEMP;
     34     while(CUR)//是否空
     35     {
     36         TEMP = CUR->next;//保存新表的当前指针的前驱指针(无前驱为NULL)
     37         CUR->next = NEW;// 逆序(NEW为新表当前CUR的后继指针)
     38         NEW = CUR;//更新新表后继指针
     39         CUR = TEMP;//更新新表当前指针      
     40     }    
     41     L->next = NEW;//逆序的头指针插入头结点
     42 }  
     43 */
     44 
     45 /* 
     46 //利用前后二个指针逐个结点分割, 利用头插法逆序
     47 void reverse(Linklist L)
     48 {
     49     Linklist CUR = L->next, NEW;
     50     L->next = NULL;
     51     while(CUR)//是否空
     52     {
     53         NEW = CUR;//保存当前指针
     54         CUR = CUR->next;//当前指针更新(为新表的前驱)
     55         NEW->next = L->next;// 新结点头插法
     56         L->next = NEW; //新结点插到头结点
     57     }      
     58 }   
     59 */
     60 
     61 /* 创建带头结点的链表 */
     62 Linklist create()
     63 {
     64     printf("输入整数若干, -1结束输入:");
     65     Linklist L,p,r;
     66     L = r = (Linklist)malloc(sizeof(NODE));
     67     L->next = NULL;
     68     int x;
     69     scanf("%d",&x);
     70     while(x!=-1)
     71     {   /* 创建新结点*/
     72         p = (Linklist)malloc(sizeof(NODE));
     73         p->data = x;
     74         p->next = NULL;
     75         /* 尾插 */
     76         r->next = p;//尾插
     77         r = p;    //更新尾指针
     78         scanf("%d",&x);
     79     }
     80     return L;
     81 }
     82 
     83 /* 打印链表 */
     84 void print(Linklist L)
     85 {
     86     if(L==NULL) return;         
     87     while(L->next)//传带头结点链表
     88     {
     89         L = L->next;
     90         printf("%5d",L->data);
     91     }
     92     printf("
    ");
     93 }
     94 
     95 int main()
     96 {    /* 创建链表并打印 */
     97     Linklist L = create();
     98     printf("原链表如下:");
     99     print(L);
    100     /* 逆序并打印 */
    101     reverse(L);//逆序
    102     printf("逆序后如下:");
    103     print(L);
    104     return 0;
    105 }
    递归,非递归逆置

     5、删除a链表若干元素插入到b链表

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 /*定义结构体*/
      4 typedef struct node NODE;
      5 typedef struct node* LINKLIST;
      6 struct node{
      7     int num;
      8     LINKLIST next;
      9 };
     10 /* 创建链表 */
     11 void create(LINKLIST* a, int n)
     12 {
     13     printf("请输入%d个整数:", n);
     14     LINKLIST r, p;
     15     *a = r = p = (LINKLIST)malloc(sizeof(NODE));
     16     p->next = NULL;
     17     scanf("%d",&p->num);
     18 
     19     for(int i=1; i<n; ++i){
     20         p = (LINKLIST)malloc(sizeof(NODE));
     21         p->next = NULL;
     22         scanf("%d",&p->num);
     23         r->next = p;
     24         r = p;
     25     }    
     26 }
     27 /* 删除并插入 */
     28 LINKLIST DelAndInsert(LINKLIST a, LINKLIST b, int i, int j, int len )
     29 {    /* 删除a链表从i开始len个元素 */
     30     if(i<=0 || j<=0 || len<=0)
     31     {
     32         printf("erro
    ");
     33         return NULL;
     34     }
     35     
     36     LINKLIST start,end, pre, t;
     37     t = a; //保存a的地址
     38     
     39     int count = 1; //第一个元素
     40     while(t && count<i+len-1){
     41         if(count==i-1) pre = t;//start之前的元素
     42         t = t->next;
     43         count++;    
     44     }
     45     if(!t && count<i+len-1)
     46     {
     47         printf("删除位置错误
    ");
     48         return a;
     49     }
     50     end = t;// 确定删除结束结点end
     51     if(i>1)
     52     {            
     53         start = pre->next; //确定删除开始结点
     54         pre->next = end->next; //删除len个元素
     55     }
     56     else
     57     {
     58         start = a;  //确定删除开始元素
     59         a = end->next; //如果等于1, end后的元素地址返回        
     60     }
     61         
     62     printf("删除a链表从第%d个元素开始共%d个元素,插入到b链表第%d个元素后
    ",
     63         i,len,j);
     64     /* 插入到b链表从j开始 */
     65     while(b && (j-1)){
     66         b = b->next;
     67         j--;
     68     }
     69     if(!b && j>0)
     70     {
     71         printf("插入位置错误
    ");
     72         return a;
     73     }
     74     end->next = b->next; //第j+1个元素插到end后
     75     b->next = start;  //start插到第j个元素后
     76     return a;
     77 }
     78 /* 打印 */
     79 void print(LINKLIST a){
     80     while(a)
     81     {
     82         printf("%5d",a->num);
     83         a = a->next;
     84     }
     85     printf("
    ");
     86 }
     87 /*
     88 1 2 3 4 5 6 7 8 9 10
     89 11 12 13 14 15 16 
     90  */
     91 int main()
     92 {   
     93     LINKLIST a, b;
     94     //int n = 10;
     95     printf("数组a,");
     96     create(&a,10);
     97     printf("数组b,");
     98     create(&b,6);
     99     a = DelAndInsert(a,b,2,1,5);
    100     printf("a链表删除后:");
    101     print(a);
    102     printf("b链表插入后:");
    103     print(b);    
    104     return 0;
    105 }
    删除并插入

     6、链表实现约瑟夫环,猴子选大王

     1 #include <stdio.h>
     2 #include <malloc.h>
     3 
     4 struct Node {
     5     int number;
     6     struct Node* next;
     7 };
     8 
     9 struct Node* CreatLinkList(int total)
    10 {
    11     struct Node *p,*t,*h; //p新结点, t当前结点, h记录第一结点
    12     for ( int i=total; i>=1; i--)
    13     {
    14         p = (struct Node*)malloc(sizeof(struct Node));
    15         p->number = i;
    16         p->next = NULL;
    17         
    18         if(i==total) t = p, h = p; //保留当前结点t第一个结点h
    19         else p->next = t, t = p;//头部插入更新当前t
    20     }
    21 
    22     h->next = t;//插到第一个结点
    23     return h; //返回第一个结点, 后继结点数字1, 1的前驱结点
    24 }
    25 
    26 void deleteNextNode(struct Node *p)
    27 {
    28     struct Node *t = p->next; //p的后继, 即删除的结点
    29     printf("本轮出圈%d
    ", t->number);
    30     p->next = t->next; //删除结点的后继, 链接到删除结点的前驱
    31     free(t);
    32 }
    33 
    34 int main()
    35 {
    36     struct Node *p = NULL;
    37     int total = 5, space = 1;
    38     scanf("%d%d",&total, &space);
    39     
    40     p = CreatLinkList(total);
    41 
    42     while(p != p->next)
    43     {
    44         for (int i = 1; i < space; i++)
    45                p = p->next;//确定删除结点的前驱
    46         deleteNextNode(p);
    47     }
    48 
    49     printf("胜利者%d
    ", p->number);
    50     free(p);
    51     
    52     return 0;
    53 }
    循环链表实现猴子选大王

    7、多项式加法

      1 /* 多项式加法(链表表示法 ) */
      2 #include <stdio.h>
      3 #include <malloc.h>
      4 
      5 struct PolyNode {  
      6     int coef; // 系数  
      7     int expon;     // 指数  
      8     struct PolyNode *link;   // 指向下一个节点的指针 
      9 }; 
     10 typedef struct PolyNode *Polynomial;
     11  
     12 //Compare
     13 int Compare(int a, int b)
     14 {
     15     int ret;
     16     if(a > b) ret = 1;
     17     else if(a < b) ret = -1;
     18     else ret = 0;
     19     return ret;
     20 }
     21 
     22 //Attach
     23 void Attach( int c, int e, Polynomial *pRear )   
     24 {   /* 由于在本函数中需要改变当前结果表达式尾项指针的值, */ 
     25     /* 所以函数传递进来的是结点指针的地址,*pRear指向尾项*/      
     26     Polynomial P;         
     27     P =(Polynomial)malloc(sizeof(struct PolyNode)); /* 申请新结点 */      
     28     P->coef = c;    /* 对新结点赋值  */      
     29     P->expon = e;      
     30     P->link = NULL;  
     31     /* 将P指向的新结点插入到当前结果表达式尾项的后面  */       
     32     (*pRear)->link = P;       
     33     *pRear = P; /* 修改pRear值 */ 
     34 } 
     35 
     36 //读入链表 
     37 Polynomial Read()
     38 {
     39     Polynomial front, rear, temp; 
     40     rear = (Polynomial) malloc(sizeof(struct PolyNode));   
     41     front = rear;
     42     int c, e;
     43     int n;
     44     printf("输入多项式的项数:");
     45     scanf("%d", &n);//n个结点
     46     printf("按指数递减顺序逐项输入多项式系数指数:");
     47     for(int i=0; i<n; i++)
     48     {       
     49         scanf("%d %d", &c, &e);
     50         Attach( c, e, &rear);     
     51     }
     52     
     53     temp = front; 
     54     front = front->link; 
     55     free(temp); 
     56     return front;  
     57 }
     58 
     59 //加法运算 
     60 Polynomial  PolyAdd (Polynomial P1, Polynomial P2) 
     61 { 
     62     Polynomial front, rear, temp; 
     63     int sum; 
     64     rear = (Polynomial) malloc(sizeof(struct PolyNode));   
     65     front = rear;        /* 由front 记录结果多项式链表头结点 */ 
     66 
     67     while ( P1 && P2 )  /* 当两个多项式都有非零项待处理时 */ 
     68     switch ( Compare(P1->expon, P2->expon) ) 
     69     { 
     70         case 1: Attach( P1->coef, P1->expon, &rear); 
     71                 P1 = P1->link; 
     72                 break; 
     73         case -1:Attach(P2->coef, P2->expon, &rear);  
     74                 P2 = P2->link; 
     75                 break; 
     76         case 0: sum = P1->coef + P2->coef;            
     77                 if ( sum ) Attach(sum, P1->expon, &rear);            
     78                 P1 = P1->link;             
     79                 P2 = P2->link;            
     80                 break; 
     81     } 
     82     /* 将未处理完的另一个多项式的所有节点依次复制到结果多项式中去 */ 
     83     for ( ; P1; P1 = P1->link ) Attach(P1->coef, P1->expon, &rear); 
     84     for ( ; P2; P2 = P2->link ) Attach(P2->coef, P2->expon, &rear); 
     85     //rear->link = NULL;  //Attach函数link域已经赋值NULL
     86     temp = front; 
     87     front = front->link; /*令front指向结果多项式第一个非零项 */ 
     88     free(temp);           /* 释放临时空表头结点 */ 
     89     return front; 
     90 }  
     91 
     92 //打印
     93 void Print(Polynomial P)
     94 {
     95     while(P)
     96     {      
     97         printf("%3d%3d ", P->coef, P->expon);              
     98         P = P->link;
     99     }
    100     printf("
    ");
    101 }
    102 
    103 int main()
    104 {
    105     Polynomial  P1, P2; 
    106     P1 = Read(); //链表P1
    107     P2 = Read(); //链表P2
    108     Print(PolyAdd(P1,P2)); //打印加法结果
    109     return 0;
    110 }
    链表多项式加法

    8、链表合并

      1 /* 
      2 假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,
      3 请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,
      4 并要求利用原表的(即A表和B表的)结点空间存放表C 
      5 算法:
      6 1、题目要求利用原链表结点空间,把链表A的头结点作为链表C的头结点;
      7 2、把链表A B的表头结点分别赋值给两个指针,比较元素值大小依次向后移动取结点;
      8 3、把取到的结点按头插法插入到链表C的头结点,会产生从大到小的顺序;
      9 4、算法采用了c++的引用的概念,避免c的指针的指针的表达;
     10 注意:
     11 1、把链表A的头结点作为链表C的头结点注意把其指针域置空,因为用的头插法;
     12 2、元素值的判断注意用if else语句,涉及到指针;
     13 3、头插法会修改结点指针域,要提前保存下一个结点的指针;
     14 4、记得释放链表B的头结点并置空;
     15 */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <limits.h>
     20 
     21 typedef struct node LinklistNode;
     22 typedef struct node* Linklist;
     23 struct node{
     24      int data;
     25      Linklist next;
     26 };
     27 
     28 /* 新结点 */
     29 Linklist NewNode(int d)
     30 {
     31     Linklist L = (Linklist)malloc(sizeof(LinklistNode));
     32     L->data = d;
     33     L->next = NULL;
     34     return L;
     35 }
     36 
     37 /* 头插 */
     38 void HeadInsert(Linklist& Head, Linklist L)
     39 {
     40     L->next = Head->next;
     41     Head->next = L;
     42 }
     43 
     44 /* 尾插 */
     45 void TailInsert(Linklist& Tail, Linklist L)
     46 {
     47     Tail->next = L;
     48     Tail = L;
     49 }
     50 
     51 /* 创建链表 */
     52 Linklist CreateLinklist()
     53 {
     54     printf("从小到大输入整数若干, -1结束输入:");
     55     Linklist L,p,r;
     56     L = r = NewNode(INT_MAX);/* 创建头结点 */
     57     /* 循环插入链表结点 */
     58     int x;
     59     scanf("%d",&x);
     60     while(x!=-1)
     61     {   /* 创建新结点*/
     62         p = NewNode(x);
     63         /* 尾插 */
     64         TailInsert(r,p);
     65         scanf("%d",&x);
     66     }
     67     return L;
     68 }
     69 
     70 Linklist MergeLinklist(Linklist& L1, Linklist& L2)
     71 {
     72     Linklist pL1 = L1->next, pL2 = L2->next, tmp = NULL;
     73     L1->next = NULL;  /* L1的头指针作为新链表的头指针 */
     74     while(pL1 && pL2)
     75     {
     76         if(pL1->data <= pL2->data){
     77             tmp = pL1->next;  /* 保存下一个结点 */
     78             HeadInsert(L1,pL1); /* 因为头插法会修改结点的指针域 */
     79             pL1 = tmp;
     80         }
     81         else{
     82             tmp = pL2->next;
     83             HeadInsert(L1,pL2);
     84             pL2 = tmp;
     85         }
     86     }
     87     while(pL1)
     88     {
     89         tmp = pL1->next;
     90         HeadInsert(L1,pL1);
     91         pL1 = tmp;
     92     }
     93     while(pL2)
     94     {
     95         tmp = pL2->next;
     96         HeadInsert(L1,pL2);
     97         pL2 = tmp;
     98     }
     99     free(L2); /* 释放L2的头结点 */
    100     L2 = NULL;
    101     return L1;
    102 }
    103 
    104 void PrintLinklist(Linklist L)
    105 {
    106     L = L->next;
    107     while(L)
    108     {
    109         printf("->%d", L->data);
    110         L = L->next;
    111     }
    112     printf("
    ");
    113 }
    114 /* 
    115 1 2 4 9 -1
    116 4 5 6 7 8 9 -1
    117 */
    118 int main()
    119 {
    120     Linklist L1 = CreateLinklist();
    121     Linklist L2 = CreateLinklist();
    122     PrintLinklist(L1);
    123     PrintLinklist(L2);
    124     PrintLinklist(MergeLinklist(L1,L2));    
    125     return 0;
    126 }
    合并,逆转链表

    9、链式字符串匹配

    #include <stdio.h>
    #include <stdlib.h>
    
    /* 
        在源串S中查找目标串T,如没有找到则打印出错信息;
        否则,在第一次匹配后请将源串S的匹配部分就地逆置
     */
     
    typedef char elementype;
    typedef struct node
    {
        elementype data;
        struct node * next;
    }linkstr;    
    
    linkstr* createstr();
    void printstr(linkstr* s);
    void reverse(linkstr* s,linkstr* e);
    void match(linkstr* s,linkstr* t);
    
    int main()
    {
        /*输入源串 */
        linkstr* head = createstr();
        /* 输入目标串 */
        linkstr* t = createstr();
        /* 匹配 */
        match(head,t);
        /* 打印源串 */
        printstr(head);
        return 0;
    }
    
    /* create */
    linkstr* createstr() 
    {
        linkstr* head, *p; 
        /* 头结点 */
        head = p = (linkstr*)malloc(sizeof(linkstr));
        
        printf("input the string
    ");
        char ch;
        linkstr* tmp = NULL;
        
        while((ch=getchar())!='
    ')
        {
            tmp = (linkstr*)malloc(sizeof(linkstr));
            tmp->data = ch;
            tmp->next = NULL;
    
            p->next = tmp;
            p = p->next;
        }
    
        return head;
    }
    
    /* 打印 */
    void printstr(linkstr* p) //输出串
    {
        p = p->next; /* 有头结点 */
        while(p)
        {
            printf("%c",p->data);
            p = p->next;
        }    
    }
    
    /* 逆序 */
    void reverse(linkstr* s,linkstr* e)
    {
         linkstr* CUR = s->next, *NEW;
         s->next = e;  /* s为逆序字符串的前驱结点 */
         while(CUR!=e)
         {
             NEW = CUR; /* 保存当前指针 */
             CUR = CUR->next; /* 当前指针更新(为新表的前驱) */
             NEW->next = s->next; /* 新结点头插法 */
             s->next = NEW;  /* 新结点插到头结点 */
         }      
    }   
    
    /* 匹配 */
    void match(linkstr* s,linkstr* t) 
    {    
        linkstr* pre = s; /* pre 为逆序需要,保存匹配字符串前驱位置 */
        linkstr* begin = s->next;//begin 源串与目标串比较的位置
        
        linkstr* p, *q;
        p = begin, q = t->next; /* p,q 源串、目标串比较开始位置 */
    
        while(p&&q)/* 在第一次匹配后 */
        {
            if (p->data==q->data)
            {
                p = p->next;
                q = q->next;
            }
            else
            {            
                pre = begin; /* 匹配字符串前驱位置 */
                begin = begin->next;
                
                p = begin; /* 更新源串 目标串比较位置 */
                q = t->next;
            }        
        }
        if (q==NULL) /* 匹配 */
        {
            reverse(pre,p); /* 匹配部分逆序 */
        }        
        else 
            printf("error!
    ");
    }
    
    朴素模式匹配,链式串的匹配及逆序
    View Code

    三、广义表也是线性表的一种推广

      广义表也是n个数据元素(d1,d2,d3,…, dn)的有限序列,但不同的是,广义表中的di既可以是单个元素,还可以是 一个广义表,通常记作:GL=(d1,d2,d3,…,dn);GL是广义表的名字, 通常用大写字母表示;n是广义表的长度;若 di是一个广义表,则称di是广 义表GL的子表; 在GL中,d1是GL的表头其余部分组成的表(d2,d3,…, dn)称为GL的表尾;广义表是递归定义的。

      1、广义表的头尾链表存储结构

    表结点可由三个域构成:标志域,指向表头的指针域,指向表 尾的指针域;元素结点只需要两个域:标志域和值域;由若干表结点串起来

    头尾链表存储,结构体:

    typedef enum {ATOM, LIST} ElemTag; /*ATOM=0,表示原子;LIST=1,表示子表*/ 
    typedef struct GLNode {
        ElemTag tag; /*标志位tag用来区别原子结点和表结点*/ 
        union {
            AtomType atom; /*原子结点的值域atom*/ 
            struct{ struct GLNode *hp, *tp; } htp; 
            /*表结点的指针域htp,包括表头指针域hp和表尾指针域tp*/ 
        }atom_htp;/*atom  htp的联合体*/ 
    } *GList;

    头尾链表存储,结构图

      2、另外,还有一种广义表存储结构,在这种结构中,无论是单元素结点还是子表结点均由三个域构成,只有一个表结点

     结构图

  • 相关阅读:
    sap快捷登录
    转载(略有修改):Windows 8的承载网络设置方法(w8 创建无线网络/ap)
    转载:Keytool 工具介绍
    minecraft初探
    linux图像界面连接-xdm
    经典的始终经典(牛蛙)
    vmware install win8 and server2012 problem
    windows硬盘优化篇
    网络15软工个人作业5——软件工程总结
    个人作业4——alpha阶段个人总结
  • 原文地址:https://www.cnblogs.com/GoldenEllipsis/p/10296216.html
Copyright © 2020-2023  润新知