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

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

/*
    该文件按习惯可以分成.h文件和实现的.cpp文件
    1、插入元素,从第0位开始
    2、类内定义的类型作为函数返回值,前面要加typename及类作用域
 */
template <class elemType>
class sLinkList
{
private:
    struct node{ //定义单链表中的结点结构
        elemType data;
        node *next;

        node(const elemType &x, node *n = NULL)
        {
            data = x; next = n;;
        }
        node() :next(NULL) {}
        ~node() {}
    };
    
    node  *head;//头指针
    int currentLength;//表长
    node *move(int i)const;//返回第i个结点的地址
    
public:
    sLinkList();
    ~sLinkList() {
        clear(); delete head;
    }

    void clear();
    int length()const {
        return currentLength;
    }
    void insert(int i, const elemType&x);
    void remove(int i);
    int search(const elemType&x)const;
    elemType visit(int i)const;
    void traverse()const;
};

// sLinkList
template <class elemType>
sLinkList<elemType> ::sLinkList()
{
    head = new node;
    currentLength = 0;
}

// clear
template <class elemType>
void sLinkList<elemType> ::clear()
{
    node *p = head->next, *q;
    head->next = NULL;
    while(p!=NULL)
    {
        q = p->next;
        delete p;
        p = q;
    }
    currentLength = 0;
}

// insert
template <class elemType>
void sLinkList<elemType> ::insert(int i, const elemType&x)
{
    node *pos;
    pos = move(i-1);
    pos->next = new node(x, pos->next);
    
    ++currentLength;
}

// 类内定义的类型作为函数返回值,前面要加typename及类作用域
// move
template <class elemType>
typename sLinkList<elemType>::node *sLinkList<elemType> :: move(int i)const
{
    node *p = head;
    while( i-- >= 0 )
    {
        p = p->next;
    }
    return p;
}  

// search
template <class elemType>
int sLinkList<elemType> :: search(const elemType&x)const
{
     node *p = head->next;
     int i=0;
     while( p != NULL && p->data != x )
     {
         p = p->next;
         ++i;
     }
     
     if(p == NULL)
         return -1;
     else
         return i;
}    
 
// visit
template <class elemType>
elemType sLinkList<elemType> :: visit(int i)const
{
     return move(i)->data;
}    
 
// traverse
template <class elemType>
void sLinkList<elemType> :: traverse()const
{
     node *p = head->next;
     cout<<endl;
     
     while( p != NULL )
     {
         cout<<p->data<<" ";
         p = p->next;
     }
     
     cout<<endl;
}    
 
// remove
template <class elemType>
void sLinkList<elemType> :: remove(int i)
{
     node *pos, *delp;
     pos = move(i-1);
     delp = pos->next;
     
     pos->next = delp->next;
     delete delp;
     
     --currentLength;
}
View Code
  1 #include <iostream>
  2 #include <cstring>
  3 using namespace std;
  4     
  5 struct student{
  6     int no;
  7     char name[20];
  8     friend ostream& operator << ( ostream &o, const student& s){
  9         o << s.no << "," << s.name; //重载运算符<<
 10         return o;
 11     }
 12 }s[2] {{1,"111"},{2,"222"}};
 13     
 14 /*
 15     该文件按习惯可以分成.h文件和实现的.cpp文件
 16     1、插入元素,从第0位开始
 17     2、类内定义的类型作为函数返回值,前面要加typename及类作用域
 18  */
 19 template <class elemType>
 20 class sLinkList
 21 {
 22 private:
 23     struct node{ //定义单链表中的结点结构
 24         elemType data;
 25         node *next;
 26 
 27         node(const elemType &x, node *n = NULL)
 28         {
 29             data = x; next = n;;
 30         }
 31         node() :next(NULL) {}
 32         ~node() {}        
 33     };
 34     
 35     node  *head;//头指针
 36     int currentLength;//表长
 37     node *move(int i)const;//返回第i个结点的地址
 38     
 39 public:
 40     sLinkList();
 41     ~sLinkList() {
 42         clear(); delete head;
 43     }
 44 
 45     void clear();
 46     int length()const {
 47         return currentLength;
 48     }
 49     void insert(int i, const elemType&x);
 50     void remove(int i);
 51     int search(const elemType&x)const;
 52     elemType visit(int i)const;
 53     void traverse()const;
 54     elemType& operator[](int i)const;
 55 };
 56 
 57 // sLinkList
 58 template <class elemType>
 59 sLinkList<elemType> ::sLinkList()
 60 {
 61     head = new node;
 62     currentLength = 0;
 63 }
 64 
 65 // clear
 66 template <class elemType>
 67 void sLinkList<elemType> ::clear()
 68 {
 69     node *p = head->next, *q;
 70     head->next = NULL;
 71     while(p!=NULL)
 72     {
 73         q = p->next;
 74         delete p;
 75         p = q;
 76     }
 77     currentLength = 0;
 78 }
 79 
 80 // insert
 81 template <class elemType>
 82 void sLinkList<elemType> ::insert(int i, const elemType&x)
 83 {
 84     node *pos;
 85     pos = move(i-1);
 86     pos->next = new node(x, pos->next);
 87     
 88     ++currentLength;
 89 }
 90 
 91 // 类内定义的类型作为函数返回值,前面要加typename及类作用域
 92 // move
 93 template <class elemType>
 94 typename sLinkList<elemType>::node *sLinkList<elemType> :: move(int i)const
 95 {
 96     node *p = head;
 97     while( i-- >= 0 )
 98     {
 99         p = p->next;
100     }
101     return p;
102 }  
103 
104 // search
105 template <class elemType>
106 int sLinkList<elemType> :: search(const elemType&x)const
107 {
108      node *p = head->next;
109      int i=0;
110      while( p != NULL && p->data != x )
111      {
112          p = p->next;
113          ++i;
114      }
115      
116      if(p == NULL)
117          return -1;
118      else
119          return i;
120 }    
121  
122 // visit
123 template <class elemType>
124 elemType sLinkList<elemType> :: visit(int i)const
125 {
126      return move(i)->data;
127 }    
128  
129 // traverse
130 template <class elemType>
131 void sLinkList<elemType> :: traverse()const
132 {
133      node *p = head->next;
134      cout<<endl;
135      
136      while( p != NULL )
137      {
138          cout<<p->data;//<<" ";
139          p = p->next;
140      }
141      
142      cout<<endl;
143 }    
144  
145 // remove
146 template <class elemType>
147 void sLinkList<elemType> :: remove(int i)
148 {
149      node *pos, *delp;
150      pos = move(i-1);
151      delp = pos->next;
152      
153      pos->next = delp->next;
154      delete delp;
155      
156      --currentLength;
157 }
158 
159 //重载[] 返回引用可以修改 可以使用[]索引链表
160 template <class elemType>
161 elemType&  sLinkList<elemType> :: operator[](int i)const
162 {    //返回类型,是链表的数据的类型
163     return   move( i )->data;
164 }    
165 
166 int main()
167 {    
168     sLinkList<student> sl;
169     sl.insert(0,s[0]);
170     sl.insert(1,s[1]);
171     //sl.traverse();
172     cout << sl[0] << endl;
173     sl[0].no = 555; //可以修改
174     cout << sl[0];
175     return 0;
176 }
View Code

二、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("申请头结点失败!\n");
 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("请输入要查找学生的学号:\n");
 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("找到符合条件的结点\n该结点为%d\t%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("  链表如下:  \n");
 75     while(p!=NULL)
 76     {
 77         printf("%d\t%.1f\n",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("释放链表:\n");
 87     while(p!=NULL)
 88     {
 89         head=head->next;
 90         free(p);
 91         p=head;
 92     }
 93     printf("释放链表成功!\n");
 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("找不到符合删除要求的结点!!!\n");
108     }
109     else //if(p1->num==num_x)
110     {
111         p2->next=p1->next;
112         free(p1);
113         printf("结点删除成功!\n");
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("有头结点链表操作程序:\n");
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("请分别输入要插入学生的学号和分数:\n");
136                 scanf("%d%f",&num,&score);
137                 p=(struct student*)malloc( sizeof(struct student) );
138                 if(p==NULL)
139                 {
140                     printf("申请该结点失败!!!\n");
141                     exit (0) ;
142                 }
143                 p->num=num;  p->score=score;   //给p赋值
144                 insert(head,p);
145                 printf("插入成功!\n");
146                 break;
147             case'P':
148                 print(head);
149                 break;
150             case'S':
151                 search(head);
152                 break;
153             case'D':
154                 printf("请输入要删除的学生的学号:\n");
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("申请头结点失败!\n");
 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("申请该结点失败!!!\n");
 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("插入成功!\n");
 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("链表为空\n");
 58         return;
 59     }
 60 
 61     printf("链表如下:  \n");
 62     while(p!=NULL)
 63     {
 64         printf("%d\t",p->num);
 65         p = p->next;
 66     }
 67     printf("\n");
 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("链表为空\n");
 77         return head;
 78     }
 79     
 80     while(p1 != NULL){ 
 81         if(p1->num == num){    //找到,删除
 82             p2->next = p1->next; //链接后续元素
 83             free(p1); // 删除元素
 84             printf("结点删除成功!\n");
 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("找不到符合删除要求的结点!!!\n");
 96     }
 97         
 98     return head;
 99 }
100 
101 int main()
102 {
103     struct node *head ;
104     char c;  
105     int num ;
106     printf("有头结点链表操作程序:\n");
107     head = create_head();
108     
109     while(1)
110     {
111         printf("i:插入结点(自动升序) p:输出链表 d:删除结点 e:退出 \n");
112         c = getch();
113         switch(c)
114         {
115             case'i':
116                 printf("请输入要插入的数据:\n");
117                 scanf("%d",&num);          
118                 insert(head,num);
119                 break;
120             case'p':
121                 print(head);
122                 break;           
123             case'd':               
124                 printf("请输入要删除结点的数据:\n");
125                 scanf("%d",&num);
126                 delete_num(head,num);                
127                 break; 
128             case'e':  
129                 exit (0) ;
130         }
131     }
132     return 0;
133 }
删除所有值为num的结点

无头结点的链表 在第k个位置插入结点 删除第k个结点

/* 无头结点的链表操作 在第k个位置插入结点或删除第k个结点 */
#include <stdio.h>
#include <stdlib.h>

struct Node{
    int data;
    struct Node* next;
};

void init(struct Node** phead){
    *phead = NULL;
}

int getLength(struct Node* head){
    int len = 0; //表长,空表为0
    while(head){
        head = head->next;
        len++;
    }
    return len;
}

struct Node* createNode(int x){
    struct Node* t;
    t = (struct Node*)malloc(sizeof(struct Node));
    t->data = x;
    t->next = NULL;
    return t;
}

void printList(struct Node* head){
    while(head){
        printf("%d,", head->data);
        head = head->next;
    }
    putchar('\n');
}

struct Node* findKth(struct Node* head, int k){
    int count = 1; //结点计数
    struct Node* p = head; //head可能为空或指向第一个结点
    while(p && count<k){ 
        p = p->next;
        count++;
    }
    return p; //表空或找到表中结点(包括表的第一及最后一个结点)
}

int insert(struct Node** phead, int k, int x){
    if(k<=0){         //无效位置 k<=0
        return 0;
    }
    else if(k==1){    //有效位置 k==1 
        struct Node* t;
        t = createNode(x);
        t->next = *phead; //表空表不空两种情况
        *phead = t;
        return 1;
    }
    else{               //k大于1(存在无效位置,k大于表长+1)
        struct Node* p;  //查找k之前的位置(结点指针)
        p = findKth(*phead,k-1);
        if(p){  // 有效位置(可以在表长+1的位置)
            struct Node* t;
            t = createNode(x);
            t->next = p->next;
            p->next = t;
            return 1;
        }
        else{ //无效位置,k大于表长+1
            return 0;
        }
    }
}

int removeNode(struct Node** phead, int k, int *px){
    if(k<1){
        return 0;
    }
    else if(k==1){
        if(*phead){
            struct Node* t = *phead;
            *phead = (*phead)->next;
            *px = t->data;
            free(t);
            return 1;
        }
        else return 0;
    }
    else{
        struct Node* p;
        p = findKth(*phead,k-1); //查找删除结点之前的位置
        if(p==NULL || p->next==NULL) 
            return 0; //表空 查找的位置是最后一个结点    
        struct Node* t;
        t = p->next;
        p->next = t->next;
        *px = t->data;
        free(t);
        return 1;
    }
}

int main(void)
{
    struct Node* head;
    init(&head);    
    insert(&head,1,11);
    insert(&head,1,22);
    insert(&head,2,33);
    insert(&head,4,44); //表长3+1的位置
    insert(&head,6,66); //无效位置 6
    insert(&head,0,1);  //无效位置 0
    printList(head);
    
    int x = 0;
    removeNode(&head,1,&x);
    printf("%d,\n",x);
    printList(head);
    
    removeNode(&head,3,&x);
    printf("%d,\n",x);
    printList(head);
    return 0;
}
View Code

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("申请头结点失败!\n");
 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("申请该结点失败!!!\n");
 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("插入成功!\n");
 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("链表为空\n");
 58         return;
 59     }
 60 
 61     printf("链表如下:  \n");
 62     while(p!=NULL)
 63     {
 64         printf("%d\t",p->num);
 65         p = p->next;
 66     }
 67     printf("\n");
 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("链表为空\n");
 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("结点删除成功!\n");
 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("找不到符合删除要求的结点!!!\n");
 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("有头结点链表操作程序:\n");
115     head = create_head();
116     
117     while(1)
118     {
119         printf("i:插入结点(自动升序) p:输出链表 d:删除结点 e:退出 \n");
120         c = getch();
121         switch(c)
122         {
123             case'i':
124                 printf("请输入要插入的数据:\n");
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:删除结点(范围)\n");
133                 c1 = getch(); //不回显
134                 switch(c1){
135                     case '1':
136                         printf("请输入要删除的结点:\n");
137                         scanf("%d",&num1);
138                         delete_num(head,del,num1); 
139                         break;
140                     case '2':
141                         printf("请输入要删除结点值的范围:\n");
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("申请头结点失败!\n");
 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("申请该结点失败!!!\n");
 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("插入成功!\n");
 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("链表为空\n");
 58         return;
 59     }
 60 
 61     printf("链表如下:  \n");
 62     while(p!=NULL)
 63     {
 64         printf("%d\t",p->num);
 65         p = p->next;
 66     }
 67     printf("\n");
 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("链表为空\n");
 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("结点删除成功!\n");
 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("找不到符合删除要求的结点!!!\n");
 96     }
 97         
 98     return head;
 99 }
100 
101 int main()
102 {
103     struct node *head ;
104     char c;  
105     int num1, num2 ;
106     printf("有头结点链表操作程序:\n");
107     head = create_head();
108     
109     while(1)
110     {
111         printf("i:插入结点(自动升序) p:输出链表 d:删除结点(范围) e:退出 \n");
112         c = getch();
113         switch(c)
114         {
115             case'i':
116                 printf("请输入要插入的数据:\n");
117                 scanf("%d",&num1);          
118                 insert(head,num1);
119                 break;
120             case'p':
121                 print(head);
122                 break;           
123             case'd':               
124                 printf("请输入要删除结点值的范围:\n");
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("\n");
 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\n");
 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("删除位置错误\n");
 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个元素后\n",
 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("插入位置错误\n");
 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("\n");
 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\n", 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\n", 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("\n");
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("\n");
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\n");
    char ch;
    linkstr* tmp = NULL;
    
    while((ch=getchar())!='\n')
    {
        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!\n");
}

朴素模式匹配,链式串的匹配及逆序
View Code

10、单链表选择排序

#include <stdio.h>
#include <stdlib.h>

/* 定义链表结点、结点及指针类型 */
typedef struct node Node, *LinkedList;  //typedef 链表结点、指针类型
struct node                //链表结点
{
    int data;
    struct node *next;
};

/* 创建并返回一个结点 */
LinkedList createLinkedListNode()  
{
    LinkedList L;
    L = (LinkedList)malloc(sizeof (struct node) );

    if(L == NULL)   //小心别漏这个
    {
        printf("申请头结点失败!\n");
        return NULL;
    }
    L->next = NULL;
    return L;
}

/*向链表插入结点*/
void insert(LinkedList &head,int num)    //参数为引用  C++的概念
{
    LinkedList s = createLinkedListNode();
    if(s == NULL)
    {
        printf("申请该结点失败!!!\n");
        exit (0) ;
    }
    s->data = num; //给s赋值

    s->next = head->next; //头插法
    head->next = s;
    
    printf("插入成功!\n");
}

/*输出链表各结点的值,也称对链表的遍历*/
void printLinkedList(LinkedList head)
{
    LinkedList p;
    p = head->next;

    if(!p)
    {
        printf("链表为空\n");
        return;
    }

    printf("链表如下:  \n");
    while(p!=NULL)
    {
        printf("%d\t",p->data);
        p = p->next;
    }
    printf("\n");
}

/* //对链表进行选择排序--数据交换
void LinkedListSort(LinkedList &L)  //参数为引用  C++的概念
{

    for(LinkedList p = L->next; p->next; p = p->next) //有头结点的链表
    {
        LinkedList t = p;   //当前结点的指针
        int temp = p->data; //当前结点的数据

        for(LinkedList q = p->next; q; q = q->next)  //从下一个结点开始
        {
            if(temp>q->data)  //如果发现小于temp的数据
            {
                temp = q->data; //更新数据
                t = q;          //更新指针
            }
        }

        if(t != p)  //如果t的指针更新了
        {
            t->data = p->data; //当前结点数据赋值到最小数据的结点
            p->data = temp;    //最小的数据赋值到当前结点
        }
    }
} */

//对链表进行选择排序--结点交换
void LinkedListSort(LinkedList &L){ //参数为引用  C++的概念
    LinkedList t,s,r;
    
    for(LinkedList p = L; p->next->next; p = p->next) //有头结点的链表
    {
        LinkedList q = p->next;   //当前结点的指针
        int temp = q->data; //当前结点的数据
        
        for(r = q,s=q; r->next; r = r->next){   //从下一个结点开始
            if( temp > r->next->data){             //如果发现小于temp的数据
                temp = r->next->data;  //更新数据
                s = r;                 //保存之前结点指针
            }
        }
        
        //输入: 2 3 4 5 1 即链表 1 5 4 3 2,以p指向1为例,来说明
        if(s->next->data <q->data )//if(temp < q->data )   即找到了最小数
        { 
            p->next=s->next; //1、把2接到原来5的前面
            s->next = q;     //2、把5接到原来2的前面 
            
            t = q->next;     //3、把原来5的后面保存
            
            q->next = p->next->next;//4、把原来2的后面接到5后面            
            p->next->next = t;        //5、把原来5的后面接到2的后面
        }        
    }    
}

int main()
{
    LinkedList head = createLinkedListNode(); //创建有头结点的空链表
    
    int n = 5, num;    //向链表插入5个结点
    while(n--){
        scanf("%d",&num);
        insert(head,num);
    }

    printLinkedList(head); //打印链表
    LinkedListSort(head);  //选择排序链表
    printLinkedList(head); //打印链表
    
    return 0;
}
View Code

11、删除所有相同数据的结点

#include <stdio.h>
#include <stdlib.h>
#include <limits>

struct node
{
    int num;
    struct node *next;
};

struct node* newNode(int num){
    struct node* p  = (struct node*)malloc(sizeof(struct node));
    p->num = num;
    p->next = NULL;
    return p;
}

struct node *createHead()
{
    struct node *head;
    head=(struct node*)malloc(sizeof (struct node) );
    if(head==NULL)      
    {
        printf("申请头结点失败!\n");
        return NULL;
    }
    head->next=NULL;
    return head;
}

//结点有序插入链表
struct node *insert(struct node *head,struct node *s)
{
    struct node *p=head;
    while( p->next!=NULL && s->num > p->next->num ){
        p=p->next;
    }
    
    s->next=p->next;
    p->next=s;    

    return head ;
}

void print(struct node *head)
{
    if(!head||!head->next)//头结点为NULL或者无数据
        return;
    struct node *p=head->next;

    printf("  链表如下:  \n");
    while(p!=NULL)
    {
        printf("%d\t",p->num);
        p=p->next;
    }
    printf("\n");
}

struct node* deleteDuplicateNumNode(struct node*  head){
    if(!head || !head->next)//头结点为NULL或者无数据
        return NULL;
        
    struct node* p = head; 
    p->num = INT_MAX;    //!!! 利用头结点数据作为第一个数据,用垃圾值可能会出错
    struct node* retHead = createHead(),*t = retHead; //创建一个返回链表头结点

    while( p->next ){    
        if( p->num != p->next->num && //第一第二个数字不同且
            ( p->next->next && p->next->num !=p->next->next->num || //第二个数字与第三个数字不同或
             !p->next->next    )                                        //没有第三个数字即为空
        )
        {//单数字摘出来
            t->next = p->next;  // 单数字(第二个数字)连接到新链表
            t = t->next;        // t指向尾结点
            p->next = t->next;      //第三个数字连接为第二个数字             
            t->next = NULL;     //尾结点赋值NULL
            continue;               //continue 返回继续判断
        }  
        p = p->next;    
    } 

    return retHead;
}

void freeList(struct node *head)
{ 
    if(head==NULL)
        return;
    struct node *p=head ;
    printf("释放链表:\n");
    while(p!=NULL)
    {
        head=head->next;
        free(p);
        p=head;
    }
    printf("释放链表成功!\n");
}

int main()
{
    struct node *head = createHead() ;    //创建一个有表头的空链表
    int arr[] = {2,1,3,4,4,5,6,3};
    //int arr[] = {2,1,3,1,1,1,1,1};
    //int arr[] = {2,1,3,4,7,5,6,8};
    //int arr[] = {2};
    
    int i=0;
    //while(i<1){
    while(i<8){
        insert( head,newNode(arr[i++]) ); //数组数字放入结点,结点插入链表
    }
    print(head);
    
    struct node *newHead = deleteDuplicateNumNode(head); //返回不含重复数字结点的新链表
    
    print(newHead);
    print(head);
    
    freeList(newHead);    
    freeList(head);
    
    return 0;
}
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、另外,还有一种广义表存储结构,在这种结构中,无论是单元素结点还是子表结点均由三个域构成,只有一个表结点

 结构图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值