链表练习整理

单链表最大值

根据已知数组建立链表

求单链表已知最大结点

本题要求求出单链表值最大的结点并返回。要求实现两个函数。
函数接口定义:

/* 建立单链表并返回单链表的头指针 */
struct Node* buildLinkedList(int* arr, int n);

/* 求单链表值最大的结点,返回指向最大值结点的指针。
 * 若单链表为空,则返回NULL。
 */
struct Node* getMax(struct Node* head);

其中arr存放创建单链表所需的数据(均为正整数),n 的值不超过1000; head 为不带附加头结点的单链表的头指针。

裁判测试程序样例:

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

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

/* 建立单链表并返回单链表的头指针 */
struct Node* buildLinkedList(int* arr, int n);

/* 求单链表值最大的结点 */
struct Node* getMax(struct Node* head);

int main(int argc, char const *argv[]) 
{
    int *a, n, i;
    scanf("%d", &n);
    a = (int*)malloc(n * sizeof(int));
    for (i = 0; i < n; ++i) {
        scanf("%d", &a[i]);
    }

    struct Node* head = NULL;

    head = buildLinkedList(a, n);

    struct Node* pMax = getMax(head);
    if (pMax)
        printf("%d\n", pMax->data);
    else
        printf("-1\n");

    free(a);

    return 0;
}
/* 请在这里填写答案 */

输入样例:

4
3 7 9 5

输出样例:

9
struct Node* buildLinkedList(int* arr, int n)//提供已知数组建立链表
{
    struct Node *p,*p1,*head=NULL;
    for(int i=0;i<n;i++)
    {
        p=(struct Node *)malloc(sizeof(struct Node));
        p->data=arr[i];
        p->next=NULL;
        if(head==NULL) head=p;
        else p1->next=p;
        p1=p;
    }
    return head;
}

struct Node* getMax(struct Node* head)//求单链表已知最大结点
{
    struct Node *p1,*max;
    p1=head->next;
    max=head;
    while(p1)
    {
        if(p1->data>max->data) max=p1;
        p1=p1->next;
    }
    return max;
}

查找学生链表

根据键盘输入数据创建链表

在链表中查询

本题要求将键盘输入的学生信息创建成单向链表,并在学生信息链表中查找学生信息。

学生信息链表结点定义如下:

typedef struct List{
  int sno;    
  char sname[10];
  List *next;
}; 

需要创建的函数包括:
创建学生信息链表函数:CreateList
查找学生信息链表函数:Find
函数接口定义:

List * CreateList();  //键盘输入若干学生学号和姓名,学号与姓名以空格符间隔,当输入的学号为-1时,输入结束,创建学生信息链表函数,返回学生链表的头指针。
List * Find(List *head, int no)  //在学生信息链表(头指针为head)中查询学号为no的学生,返回该学生结点的指针。

裁判测试程序样例:

int main(void){
    List *list=NULL,*p;
    int no;
    list=CreateList();
    while(~scanf("%d", &no))
    {
        p=Find(list,no);
        if( p ) printf("%s\n", p->sname);
        else printf("Not Found!\n");
    }
    return 0;
}
/* 请在这里填写答案 */

输入样例1:

20180002 王红
20180006 张勇
20180008 吴涛
20170010 林玉
-1 xx
20180002

输出样例1:
在这里给出相应的输出。例如:

王红

输入样例2:

20180002 王红
20180006 张勇
20180008 吴涛
20170010 林玉
-1 xx
20170015

输出样例2:

Not Found!
List * CreateList()  //键盘输入若干学生学号和姓名,学号与姓名以空格符间隔,当输入的学号为-1时,输入结束,创建学生信息链表函数,返回学生链表的头指针。
{
    List *p,*p1,*head=NULL;
    int x;
    char name[10];
    while(1)
    {
        scanf("%d",&x);
        if(x==-1)//注意该地方对“XX”的处理,p->sname=name会编译错误
        {
            scanf("%s",name);
            break;
        }
        p=(List *)malloc(sizeof(List));
        p->sno=x;
        scanf("%s",p->sname);
        p->next=NULL;
        if(head==NULL) head=p;
        else p1->next=p;
        p1=p;
    }
    return head;//不可忘!!!
}
List * Find(List *head, int no)  //在学生信息链表(头指针为head)中查询学号为no的学生,返回该学生结点的指针。
{
    List *p1=head;
    while(p1)
    {
        if(p1->sno==no) break;
        p1=p1->next;
    }
    return p1;
}

工作备忘录的生成(链表)

添加至链表,排序

如果某项工作与若干项工作冲突(在做该项工作时,需要同时做其它工作),则在该工作名前加’*'。

每天都要处理很多事务,为了更好地安排工作,希望在每天开始工作前,根据工作记录,生成工作备忘录。首先输入工作记录数(大于0的一个整数),再逐条输入各条工作记录,每条工作记录包括:工作名,开始时间,结束时间。假设每项工作的开始时间均小于它的结束时间,并且各项工作的开始时间互不相同。

我们的工作是需要把这些工作记录按开始时间排序并输出,在输出时,如果某项工作与若干项工作冲突(在做该项工作时,需要同时做其它工作),则在该工作名前加’*'。

函数接口定义:

Node* add(Node *, Node *);
void display(Node *);

裁判测试程序样例:

#include<iostream>
#include <string>
using namespace std;
struct Node{
    string name;
    int start;
    int end;
    Node *next;
};
Node* add(Node *, Node *);
void display(Node *);
bool check(Node *head)
{
    if(head==NULL || head->next==NULL) return true;
    Node *p=head->next;
    if(head->start > p->start) return false;
    return check(p);
}
int main()
{
    Node *head=NULL, *p;
    int i, repeat;
    cin>>repeat;
    for(i=0;i<repeat;i++){
        p = new Node;
        cin>>p->name>>p->start>>p->end;
        p->next=NULL;
        head = add(head, p);
    }
    if(!check(head)) cout<<"ERROR"<<endl;
    display(head);
    return 0;
}

/* 请在这里填写答案 */

输入样例:

4
aaa 19 20
ccc 169 200
ddd 153 170
bbb 20 111

输出样例:

aaa 19 20
bbb 20 111
*ddd 153 170
*ccc 169 200
Node *add(Node *head, Node *p)//添加至链表,排序
{
    Node *p1,*p2;
    p1=head;
    p2=p1;
    while(p1)
    {
        if(p->start<p1->start) break;//题目的排序要求:按开始时间排序
        p2=p1;
        p1=p1->next;
    }
    if(p1==head) //从头结点插入的情况要单独讨论
    {
        head=p;
        p->next=p1;
    }
    else{
        p->next=p1;
        p2->next=p;
    }
    return head;
}

void display(Node *head)//如果某项工作与若干项工作冲突(在做该项工作时,需要同时做其它工作),则在该工作名前加'*'。
{
    Node *p1,*p2;
    p1=head;
    int k;//标志是否与其他工作冲突
    while(p1)
    {
        k=0;
        p2=head;
        while(!k&&p2!=p1)//在链表中,若p2排在p1前面,则可能p2->end>p1->start
        {
            if(p2->end>p1->start)
            {
                k=1;
                break;
            }
            p2=p2->next;
        }
        p2=p1->next;
        while(!k&&p2)//在链表中,若p2排在p1后面,则可能p1->end>p2->start
        {
        	if(p1->end>p2->start)
        	{
        		k=1;
        		break;
			}
			p2=p2->next;
		}
        if(k==1) cout<<"*";
        cout<<p1->name<<' '<<p1->start<<' '<<p1->end<<endl;
        p1=p1->next;
    }
}

单链表(流浪狗收养所)

插入,排序

清除排序在前的数据

怡山小学生物组的同学在课外要收养一批流浪狗。在流浪狗进入收养基地时,课外指导老师会给每一只狗取一个唯一的编号,并且判定它的年龄,让组长输入流浪狗档案。档案以单链表存储,按年龄为序(从小到大),如果年龄相同,则后录入的记录应该放在前面。

由于组里新来了一位二年级的淘气组员小林,喜欢将已经输入的档案再次输入。他在输入时,会输入正确的编号,却可能输入错误的年龄(但他所输入的年龄不会大于真实的年龄),因此在输入档案外,组长还需要对档案进行清理,清除那些重复档案。

输入时:首先输入任务类型:1代表插入新的记录, 2代表清理档案, 0代表退出。如果需要加入新的记录,则接下来将依次输入编号和年龄。

输出时:按照从前到后的顺序输出档案中的所有的记录,每条记录单独占一行。

函数接口定义:

Dog *insert(string &no, int age);  //加入一只狗的信息
Dog *clear();  //清理档案

裁判测试程序样例:


#include <iostream>
#include <string>
using namespace std;
struct Dog{
  string no;
  int age;
  Dog *next;    
};
Dog *head=NULL;
void *del(Dog *p){
  if(p!=NULL)    {
    del(p->next);
    delete p;
  }
}
void display(Dog *p){
    if(p!=NULL){
        cout<<p->no<<' '<<p->age<<endl;
        display(p->next);
    }
}

Dog *clear();
Dog *insert(string &no, int age);

int main()
{

    int task, age;
    string no;
    cin>>task;
    while(task>0){
        switch(task){
            case 1:cin>>no>>age; head=insert(no, age); display(head); break;
            case 2:head=clear(); display(head); break;
        }
        cin>>task;
    }
    del(head);
    return 0;    
}

/* 请在这里填写答案 */

输入样例:

1 abcd 2
1 cd 5
1 cd 4
1 zz 4
2
0

输出样例:

abcd 2
abcd 2
cd 5
abcd 2
cd 4
cd 5
abcd 2
zz 4
cd 4
cd 5
abcd 2
zz 4
cd 5
Dog *insert(string &no, int age)//加入一只狗的信息,排序
{
    Dog *p,*p1,*p2;
    p1=head;
    p2=p1;
    p=new Dog;
    p->no=no;
    p->age=age;
    p->next=NULL;
    while(p1)
    {
        if(p->age<=p1->age) break;
        p2=p1;
        p1=p1->next;
    }
    if(p1==head)//插入讨论头结点
    {
        head=p;
        p->next=p1;
    }
    else{
        p->next=p1;
        p2->next=p;
    }
    return head;
}

Dog *clear() //清理档案,清除排序在前的数据
{
    Dog *p1,*p2,*p3;
    p1=head;
    p3=p1;
    while(p1)
    {
        p2=p1->next;
        while(p2)
        {
            if(p1->no==p2->no) break;
            p2=p2->next;
        }
        if(p2)//不要用if(p1->no==p2->no),当p2为空时会产生段错误
        {
        	if(p1==head)
        	{
        		head=p1->next;
        		p1=head;
        		p3=p1;
			}
			else
			{
				p3->next=p1->next;
				p1=p3->next;
			}
		}
		else
		{
			p3=p1;//不要出现在循环开始的时候
			p1=p1->next;
		}
    }
    return head;
}

判断链表结点对称

循环双链表不可以用p1!=NULL

设计算法,判断带头结点的循环双向链表中的数据结点是否对称。
如果对称,输出“yes”
如果不对称,输出“no”
链表空则输出“NULL”

链表结构及操作函数接口定义:


typedef char ElemType;
typedef struct DNode    //定义循环双链表结点类型
{    
    ElemType data;
    struct DNode *prior,*next;
} DLinkNode;
void InitList(DLinkNode *&L);        //初始化一个空的带头节点的双向循环链表  裁判程序实现,略去不表
void DestroyList(DLinkNode *&L);  // 销毁链表  裁判程序实现,略去不表
bool ListInsert(DLinkNode *&L,int i,ElemType e); // 在链表第i个节点处插入元素为e的节点 。裁判程序实现,略去不表。

void DispList(DLinkNode *L);  // 正向顺序输出链表,输出时每个节点元素之间以空格符间隔,以换行符结束。
int Symm(DLinkNode *L);  // 判断链表是否对称,对称时返回1,不对称时返回0,链表为空时返回-1。

裁判测试程序样例:

#include <stdio.h>

void InitList(DLinkNode *&L);        //裁判程序实现,略去不表
void DestroyList(DLinkNode *&L);  //裁判程序实现,略去不表
bool ListInsert(DLinkNode *&L,int i,ElemType e);//裁判程序实现,略去不表
//要求写出以下函数实现
void DispList(DLinkNode *L);
int Symm(DLinkNode *L);

int main()
{
    DLinkNode *h;
    ElemType e;
    InitList(h);
    int i=1;
    char ch;
    while((ch=getchar())!='\n')
    {
        ListInsert(h,i,ch);
        i++;
    }
    DispList(h);

    if(Symm(h)==1)
        printf("yes\n");
    else if (Symm(h)==0)printf("no\n");
    else printf("NULL\n");
    DestroyList(h);
    return 0;
}

/* 请在这里填写答案 */

输入样例:
在这里给出一组输入。例如:

abcxba

输出样例:
在这里给出相应的输出。例如:

a b c x b a 
no
void DispList(DLinkNode *L)// 正向顺序输出链表,输出时每个节点元素之间以空格符间隔,以换行符结束。
{
    DLinkNode *p1;
    p1=L->next;
    while(p1!=L)//因为是循环双向链表,所以不可以用p1!=NULL
    {
        printf("%c",p1->data);
        printf(" ");
        p1=p1->next;
    }
    printf("\n");
}
int Symm(DLinkNode *L)// 判断链表是否对称,对称时返回1,不对称时返回0,链表为空时返回-1。
{
    DLinkNode *p1,*p2;
    if(L->next==L) return -1;
    p1=L->next;
    p2=L->prior;
    while(p1!=p2)
    {
        if(p1->data!=p2->data) return 0;
        p1=p1->next;
        p2=p2->prior;
    }
    return 1;
}

集合的基本运算(单链表)

带头结点链表

数组元素值尾插法创建链表

销毁链表

单链表元素递增排序,交换已知链表中数据的顺序

求两有序集合ha、hb的并集hc,建立hc

求两有序集合ha、hb的的交集hc

求两有序集合ha、hb的差集hc,差集概念,x对x的差集

有两个字符集合A和B,现在要求实现集合的并、交、差运算。
要求:集合用单链表表示,假设同一个集合中不存在重复的元素。A、B集合元素最多不超过100个,至少有一个元素。
算法实现:
1)将两个集合的元素按递增方式排序,构成有序单链表。
2)采用二路归并算法求集合的并集、交集和差集。

链表结构及操作函数接口定义:

typedef char ElemType;
typedef struct LNode    //定义单链表结点类型
{
      ElemType data;
    struct LNode *next;
} LinkList;
void DispList(LinkList *L);  //输出链表元素,每个结点元素值以空格符间隔,以换行符结束。
void CreateListR(LinkList *&L,ElemType a[],int n); //用数组元素值尾插法创建链表。
void DestroyList(LinkList *&L);//销毁链表。
void sort(LinkList *&L)        //单链表元素递增排序。
void Union(LinkList *ha,LinkList *hb,LinkList *&hc)  //求两有序集合ha、hb的并集hc。
void InterSect(LinkList *ha,LinkList *hb,LinkList *&hc)    //求两有序集合ha、hb的的交集hc。
void Subs(LinkList *ha,LinkList *hb,LinkList *&hc)    //求两有序集合ha、hb的差集hc。

裁判测试程序样例:

#include <stdio.h>
#include <malloc.h>
int main()
{
    LinkList *ha,*hb,*hc;
    ElemType a[100]={0};
    ElemType b[100]={0};
    int i=0;
    char ch;
    while((ch=getchar())!='\n')
    {
        a[i++]=ch;
    }
    CreateListR(ha,a,i);
    i=0;
    while((ch=getchar())!='\n')
    {
        b[i++]=ch;
    }
    CreateListR(hb,b,i);
    printf("A: ");DispList(ha);
    printf("B: ");DispList(hb);
    sort(ha);
    sort(hb);
    printf("sorted A: ");DispList(ha);
    printf("sorted B: ");DispList(hb);
    Union(ha,hb,hc);
    printf("Union C: ");DispList(hc);
    InterSect(ha,hb,hc);
    printf("InterSect C: ");DispList(hc);
    Subs(ha,hb,hc);
    printf("Subs C: ");DispList(hc);
    DestroyList(ha);
    DestroyList(hb);
    DestroyList(hc);
    return 0;
}
/* 请在这里填写答案 */

输入样例:
在这里给出一组输入。例如:

adecfgvjkz
akidqe

输出样例:
在这里给出相应的输出。例如:

A: a d e c f g v j k z 
B: a k i d q e 
sorted A: a c d e f g j k v z 
sorted B: a d e i k q 
Union C: a c d e f g i j k q v z 
InterSect C: a d e k 
Subs C: c f g j v  z 
void DispList(LinkList *L)  //输出链表元素,每个结点元素值以空格符间隔,以换行符结束。
{
	
    LinkList *p1;
    p1=L->next;
    while(p1)
    {
        printf("%c",p1->data);
        printf(" ");
        p1=p1->next;
    }
    printf("\n");
}

void CreateListR(LinkList *&L,ElemType a[],int n) //用数组元素值尾插法创建链表。
{
    LinkList *p,*p1;
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
    p1=L;
    for(int i=0;i<n;i++)
    {
        p=(LinkList *)malloc(sizeof(LinkList));
        p->data=a[i];
        p->next=NULL;
        p1->next=p;
        p1=p;
    }
}

void DestroyList(LinkList *&L)//销毁链表。
{
    LinkList *p1,*p2;
    p1=L;
    while(p1)
    {
        p2=p1;
        p1=p1->next;
        free(p2);
    }
}

void sort(LinkList *&L)        //单链表元素递增排序,交换已知链表中数据的顺序
{
    LinkList *p,*p1,*p2;
    p1=L->next;
    while(p1)
    {
        p2=p1->next;
        while(p2)
        {
            if(p2->data<p1->data)
            {
                char t;
                t=p1->data;
                p1->data=p2->data;
                p2->data=t;
            }
            p2=p2->next;
        }
        p1=p1->next;
    }
}

void Union(LinkList *ha,LinkList *hb,LinkList *&hc)  //求两有序集合ha、hb的并集hc,建立hc
{
    LinkList *p1,*p2,*p3,*p;
    p1=ha->next;
    p2=hb->next;
    hc=(LinkList *)malloc(sizeof(LinkList));
    p3=hc;
    while(p1&&p2)
    {
        if(p1->data<p2->data) 
        {
            p=(LinkList *)malloc(sizeof(LinkList));
            p->data=p1->data;
            p->next=NULL;
            p3->next=p;
            p3=p;
            p1=p1->next;
        }
        else if(p1->data>p2->data) 
        {
            p=(LinkList *)malloc(sizeof(LinkList));
            p->data=p2->data;
            p->next=NULL;
            p3->next=p;
            p3=p;
            p2=p2->next;
        }
        else{
            p=(LinkList *)malloc(sizeof(LinkList));
            p->data=p1->data;
            p->next=NULL;
            p3->next=p;
            p3=p;
            p1=p1->next;
            p2=p2->next;
        }
    }
    while(p1)
    {
        p=(LinkList *)malloc(sizeof(LinkList));
        p->data=p1->data;
        p->next=NULL;
        p3->next=p;
        p3=p;
        p1=p1->next;
    }
    while(p2)
    {
        p=(LinkList *)malloc(sizeof(LinkList));
        p->data=p2->data;
        p->next=NULL;
        p3->next=p;
        p3=p;
        p2=p2->next;
    }
}

void InterSect(LinkList *ha,LinkList *hb,LinkList *&hc)    //求两有序集合ha、hb的的交集hc。
{
    LinkList *p1,*p2,*p3,*p;
    p1=ha->next;
    p2=hb->next;
    hc=(LinkList *)malloc(sizeof(LinkList));
    p3=hc;
    while(p1)
    {
        while(p2)
        {
            if(p1->data==p2->data) break;
            p2=p2->next;
        }
        if(p2)
        {
            p=(LinkList *)malloc(sizeof(LinkList));
            p->data=p1->data;
            p->next=NULL;
            p3->next=p;
            p3=p;
        }
        p2=hb->next;
        p1=p1->next;
    }
}

void Subs(LinkList *ha,LinkList *hb,LinkList *&hc)    //求两有序集合ha、hb的差集hc,差集概念,x对x的差集
{
    LinkList *p1,*p2,*p3,*p;
    p1=ha->next;
    p2=hb->next;
    hc=(LinkList *)malloc(sizeof(LinkList));
    p3=hc;
    while(p1)
    {
        while(p2)
        {
            if(p1->data==p2->data) break;
            p2=p2->next;
        }
        if(!p2)
        {
            p=(LinkList *)malloc(sizeof(LinkList));
            p->data=p1->data;
            p->next=NULL;
            p3->next=p;
            p3=p;
        }
        p2=hb->next;
        p1=p1->next;
    }
}

链表拼接

合并两个有序链表,不带头结点,重复数据不删

本题要求实现一个合并两个有序链表的简单函数。链表结点定义如下:

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

函数接口定义:

struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);

其中list1和list2是用户传入的两个按data升序链接的链表的头指针;函数mergelists将两个链表合并成一个按data升序链接的链表,并返回结果链表的头指针。

裁判测试程序样例:

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

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

struct ListNode *createlist(); /*裁判实现,细节不表*/
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2);
void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode  *list1, *list2;

    list1 = createlist();
    list2 = createlist();
    list1 = mergelists(list1, list2);
    printlist(list1);
    
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

1 3 5 7 -1
2 4 6 -1

输出样例:

1 2 3 4 5 6 7 
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2)//合并两个有序链表,不带头结点,重复数据不删
{
    struct ListNode *head=NULL,*p1,*p2,*p,*p4;
    p1=list1;
    p2=list2;
    while(p1&&p2)
    {
        if(p1->data<p2->data)
        {
            p=(struct ListNode *)malloc(sizeof(struct ListNode));
            p->data=p1->data;
            p->next=NULL;
            if(head==NULL) head=p;
            else p4->next=p;
            p4=p;
            p1=p1->next;
        }
        else
        {
            p=(struct ListNode *)malloc(sizeof(struct ListNode));
            p->data=p2->data;
            p->next=NULL;
            if(head==NULL) head=p;
            else p4->next=p;
            p4=p;
            p2=p2->next;
        }
    }
    while(p1)
    {
        p=(struct ListNode *)malloc(sizeof(struct ListNode));
        p->data=p1->data;
        p->next=NULL;
        if(head==NULL) head=p;
        else p4->next=p;
        p4=p;
        p1=p1->next;
    }
    while(p2)
    {
        p=(struct ListNode *)malloc(sizeof(struct ListNode));
        p->data=p2->data;
        p->next=NULL;
        if(head==NULL) head=p;
        else p4->next=p;
        p4=p;
        p2=p2->next;
    }
    return head;
}

奇数值结点链表

删除并新建链表

本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中奇数值的结点重新组成一个新的链表。链表结点定义如下:

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

函数接口定义:

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );

函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。

函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。

裁判测试程序样例:

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

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

struct ListNode *readlist();
struct ListNode *getodd( struct ListNode **L );
void printlist( struct ListNode *L )
{
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *L, *Odd;
    L = readlist();
    Odd = getodd(&L);
    printlist(Odd);
    printlist(L);

    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

1 2 2 3 4 5 6 7 -1

输出样例:

1 3 5 7 
2 2 4 6 
struct ListNode *readlist()
{
    struct ListNode *head=NULL,*p1,*p;
    int n;
    while(1)
    {
        scanf("%d",&n);
        if(n==-1) break;
        p=(struct ListNode *)malloc(sizeof(struct ListNode));
        p->data=n;
        p->next=NULL;
        if(head==NULL) head=p;
        else p1->next=p;
        p1=p;
    }
    return head;
}

struct ListNode *getodd( struct ListNode **L )//删除后新建链表
{
    struct ListNode *head=NULL,*p1,*p2,*p,*p3;
    p1=*L;
    p2=p1;
    while(p1)
    {
        if(p1->data%2!=0)
        {
            p=(struct ListNode *)malloc(sizeof(struct ListNode));
            p->data=p1->data;
            p->next=NULL;
            if(head==NULL) head=p;//新建链表
            else p3->next=p;
            p3=p;
            if(p1==*L)//删除,讨论头结点
            {
                *L=p1->next;
                p1=*L;
                p2=p1;
            }
            else{
                p2->next=p1->next;
                p1=p2->next;
            }
        }
        else{
            p2=p1;
            p1=p1->next;
        }
    }
    return head;
}

创建单链表

头插法和尾插法

本题要求实现单链表的头插法和尾插法建表。
要求写出CreateListF函数、 CreateListR函数和DispList函数。
说明:单链表带头结点。

链表结构及操作函数接口定义:

typedef char ElemType;
typedef struct LNode          //定义单链表结点类型
{
    ElemType data;
    struct LNode *next;        //指向后继结点
} LinkList;

LinkList *  CreateListF(LinkList *L,ElemType a[],int n);//用数组元素值头插法建立单链表,返回单链表头结点指针。
LinkList *  CreateListR(LinkList *L,ElemType a[],int n);//用数组元素值尾插法建立单链表,返回单链表头结点指针。
void DispList(LinkList *L);     //输出单链表所有结点,如果链表为空,则输出NULL
void SetListNULL(LinkList *L);  //裁判程序实现,删除链表所有数据结点,将链表置为空表。 

裁判测试程序样例:

#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct LNode          //定义单链表结点类型
{
    ElemType data;
    struct LNode *next;        //指向后继结点
} LinkList;

LinkList * CreateListF(LinkList *L,ElemType a[],int n);//头插法建立单链表。
LinkList * CreateListR(LinkList *L,ElemType a[],int n);//尾插法建立单链表。
void DispList(LinkList *L); //输出单链表所有结点值,每个结点之间用空格间隔,如果链表为空,则输出NULL。全部输出用换行符结束。 
void SetListNULL(LinkList *L);//删除链表所有数据结点,将链表置为空表。 裁判程序实现。

int main()
{
    LinkList *L, *ha,*hb;
    ElemType a[100]={0};
    int i=0;
    char ch;
    while((ch=getchar())!='\n')
    {
        a[i++]=ch;
    }        
    ha=CreateListR(L,a,i);
    hb=CreateListF(L,a,i);
    printf("A: ");DispList(ha);
    printf("B: ");DispList(hb);
        SetListNULL(ha);
    SetListNULL(hb);
    printf("A: ");DispList(ha);
    printf("B: ");DispList(hb);    
    return 0;
}

void SetListNULL(LinkList *L);// 裁判程序实现,细节不表。删除链表所有数据结点,将链表置为空表。
{
...
}

/* 请在这里填写答案 */

输入样例:
在这里给出一组输入。例如:

abcdef

输出样例:
在这里给出相应的输出。例如:

A: a b c d e f 
B: f e d c b a 
A: NULL 
B: NULL 
LinkList *  CreateListF(LinkList *L,ElemType a[],int n)//用数组元素值头插法建立单链表,返回单链表头结点指针。
{
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
    LinkList *p;
    for(int i=0;i<n;i++)
    {
        p=(LinkList *)malloc(sizeof(LinkList));
        p->data=a[i];
        p->next=L->next;
        L->next=p;
    }
    return L;
}

LinkList *  CreateListR(LinkList *L,ElemType a[],int n)//用数组元素值尾插法建立单链表,返回单链表头结点指针。
{
     L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
    LinkList *p1,*p;
    p1=L;
    for(int i=0;i<n;i++)
    {
        p=(LinkList *)malloc(sizeof(LinkList));
        p->data=a[i];
        p->next=NULL;
        p1->next=p;
        p1=p;
    }
    return L;
}

void DispList(LinkList *L)     //输出单链表所有结点,如果链表为空,则输出NULL
{
    LinkList *p1;
    if(L->next==NULL) printf("NULL");
    p1=L->next;
    while(p1)
    {
        printf("%c ",p1->data);
        p1=p1->next;
    }
    printf("\n");
}

单链表逆置

间接头插

已知单链表的结点结构定义如下:

typedef struct _NODE_
{
    int data;
    struct _NODE_ *next;
} NODE;

说明:data 为数据域。next 为指针域,指示后继结点。
请编写函数,将带附加头结点的单链表逆置。
函数原型

void Reverse(NODE *head);

说明:参数 head 为单链表的头指针。函数将单链表中数据元素的排列顺序颠倒过来。
裁判程序

int main()
{
    NODE *h;
    Create(&h);
    Input(h);
    Reverse(h);
    Output(h);
    putchar('\n');
    Destroy(&h);
    return 0;
}

说明:Create 函数用于创建链表,Destroy 函数用于销毁链表。Input 函数用于输入链表:首先输入结点数,然后输入这些数据元素。Output 函数用于输出单链表,数据元素之间以空格间隔。
输入样例

5
28 47 79 52 36

输出样例

36 52 79 47 28
void Reverse(NODE *head)
{
    NODE *p1,*p2;
    p1=head->next;
    head->next=NULL;
    while(p1)
    {
        p2=p1;
        p1=p1->next;
        p2->next=head->next;
        head->next=p2;
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值