数据结构(c语言版)(第三版)实验3

1、实验3 带头节点的单链表

运行环境:Dev-C++

一、实验目的

1.理解带头节点的单链表的特点,掌握其基本操作。

2.熟练掌握运用带头节点链表表示特定形式的数据的方法,并设计出有关算法。

二、实验内容

已知带头节点的链表结构定义及头插法建表,尾插法建表和打印链表等函数定义如下(详见slnklist.h文件),基于该内容完成实验题1~实验9。

#include <stdio.h>
#include <stdlib.h>
/**************************************/
/* 链表实现的头文件,文件名slnklist.h */
/**************************************/
 typedef int datatype;
 typedef struct link_node{
   datatype info;
   struct link_node *next;
 }node;
typedef node *linklist;
/******************************************/
/*函数名称:creatbystack()                 */
/*函数功能:头插法建立带头结点的单链表    */
/******************************************/
linklist creatbystack()
{
​
    linklist  head,s;
    datatype x;
    head=(linklist)malloc(sizeof(node));
    head->next=NULL;
​
    printf("请输入整数序列(空格分开,以0结束):\n");
    scanf("%d",&x);
    while (x!=0)
    {
        s=(linklist)malloc(sizeof(node));
        s->info=x;
​
        s->next=head->next;
        head->next=s;
​
        scanf("%d",&x);
    }
    return head;
}
/***************************************/
/*函数名称:creatbyqueue()              */
/*函数功能:尾插法建立带头结点的单链表 */
/***************************************/
linklist creatbyqueue()
{
    linklist head,r,s;
    datatype x;
    head=r=(linklist)malloc(sizeof(node));
    head->next=NULL;
    printf("请输入整数序列(空格分开,以0结束):\n");
    scanf("%d",&x);
    while (x!=0)
    {
         s=(linklist)malloc(sizeof(node));
         s->info=x;
         r->next=s;
         r=s;
         scanf("%d",&x);
   }
    r->next=NULL;
    return head;
}
/**********************************/
/*函数名称:print()                   */
/*函数功能:输出带头结点的单链表      */
/**********************************/
void print(linklist head)
{
    linklist p;
    int i=0;
    p=head->next;
    printf("List is:\n");
    while(p)
    {
        printf("%7d",p->info);
        i++;
        if (i%10==0)    printf("\n");
        p=p->next;
    }
    printf("\n");
​
}
​
/******************************************/
/*函数名称:creatLink()                */
/*函数功能:从文件中读入n个数据构成单链表 */
/******************************************/
linklist creatLink(char *f, int n)
{
    FILE *fp;
    int i;
    linklist s,head,r;
    head=r=(linklist)malloc(sizeof(node));
    head->next=NULL;
    fp=fopen(f,"r");
    if (fp==NULL)
        return head;
    else
    {
         for (i=0;i<n;i++)
            {
                s=(linklist)malloc(sizeof(node));
                fscanf(fp,"%d",&(s->info));
                r->next=s;
                r=s;
            }
        r->next=NULL;
        fclose(fp);
        return head;
    }
}
​
/*
    函数名称:writetofile
    函数功能:将链表内容存入文件f
*/
void writetofile(linklist head, char *f)
{
    FILE *fp;
    linklist p;
    int i=0;
    fp=fopen(f,"w");
    if (fp!=NULL)
    {
        p=head->next;
        fprintf(fp,"%s","List is:\n");
        while(p)
        {
            fprintf(fp,"%7d",p->info);
            i++;
            if (i%10==0)    fprintf(fp,"%c",'\n');
            p=p->next;
        }
        fprintf(fp,"%c",'\n');
        fclose(fp);
    }
    else    printf("创建文件失败!");
​
}
​
​
/**********************************/
/*函数名称:delList()                 */
/*函数功能:释放带头结点的单链表      */
/**********************************/
void delList(linklist head)
{ linklist p=head;
  while (p)
  { head=p->next;
    free(p);
    p=head;
  }
}

实验3.1

编写函数void delx(linklist head, datatype x),删除带头结点单链表head中第一个值为x 的结点。 并构造测试用例进行测试。

/*编写函数void delx(linklist head, datatype x),删除带头结点单链表head中第一个值为x 的结点。
并构造测试用例进行测试。
*/
/**********************************/
/*文件名称:lab3_01.c                 */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist delx(linklist head,datatype x)
{
    node* p=head;
    node* q=p->next;
    while(q){
        if(q->info==x){
            p->next=q->next;
            return head;
            break;
        }
        p=p->next;
        q=q->next;
    } 
}
​
int main()
{   datatype x;
    linklist head;
    head=creatbyqueue();        /*尾插入法建立带头结点的单链表*/
    print(head);
    printf("请输入要删除的值:");
    scanf("%d",&x);
    head=delx(head,x);          /*删除单链表的第一个值为x的结点*/
    print(head);
    delList(head);              /*释放单链表空间*/
    return 0;
}

实验3.2

假设线性表(a1,a2,a3,…an)采用带头结点的单链表存储,请设计算法函数linklist reverse(linklist head), 将带头结点的单链表head就地倒置,使表变成(an,an-1,…a3.a2,a1)。并构造测试用例进行测试。

/**********************************/
/*文件名称:lab3_02.c                 */
/**********************************/
/*
假设线性表(a1,a2,a3,…an)采用带头结点的单链表存储,请设计算法函数linklist reverse(linklist  head),
将带头结点的单链表head就地倒置,使表变成(an,an-1,…a3.a2,a1)。并构造测试用例进行测试。
*/
#include "slnklist.h"
#include<iostream>
using namespace std;
#include<vector>
/*请将本函数补充完整,并进行测试*/
linklist reverse(linklist head)
{
    vector<int> a;
    node* p=head->next;
    while(p){
        a.push_back(p->info);
        p=p->next;
    }
    p=head->next;
    while(p){
        p->info=a.back();
        a.pop_back();
        p=p->next; 
    }
    return head;
}
int main()
{   datatype x;
    linklist head;
    head=creatbystack();            /*头插入法建立带头结点的单链表*/
    print(head);                    /*输出原链表*/
    head= reverse(head);            /*倒置单链表*/
    print(head);                    /*输出倒置后的链表*/
    delList(head);
    return 0;
}

实验3.3

假设带头结点的单链表head是升序排列的,设计算法函数linklist insert(linklist head,datatype x), 将值为x的结点插入到链表head中,并保持链表有序性。 分别构造插入到表头、表中和表尾三种情况的测试用例进行测试。

/*
假设带头结点的单链表head是升序排列的,设计算法函数linklist insert(linklist head,datatype x),
将值为x的结点插入到链表head中,并保持链表有序性。
分别构造插入到表头、表中和表尾三种情况的测试用例进行测试。
*/
/**********************************/
/*文件名称:lab3_03.c                 */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist insert(linklist head ,datatype x)
{
    node* p=head;
    node* q=p->next;
    while(q){
        if(q->info>x){
            node* a=(node*)malloc(sizeof(node));
            p->next=a;
            a->info=x;
            a->next=q;
            return head;
        }
        else{
            p=p->next;
            q=q->next;
        }
    }
        if(q==NULL){
            node* a=(node*)malloc(sizeof(node));
            p->next=a;
            a->info=x;
            a->next=NULL;
            return head;
        }
}
int main()
{   datatype x;
    linklist head;
    printf("输入一组升序排列的整数:\n");
    head=creatbyqueue();                /*尾插入法建立带头结点的单链表*/
    print(head);
    printf("请输入要插入的值:");
    scanf("%d",&x);
    head=insert(head,x);                /*将输入的值插入到带头结点的单链表适当位置*/
    print(head);
    delList(head);
    return 0;
}

实验3.4

编写算法函数linklist delallx(linklist head, int x),删除带头结点单链表head中所有值为x的结点。

/*
编写算法函数linklist delallx(linklist head, int x),删除带头结点单链表head中所有值为x的结点。
*/
/**********************************/
/*文件名称:lab3_04.c                 */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist delallx(linklist head,int x)
{
    node* p=head;
    node* q=head->next;
    while(q){
        if(q->info==x){
            p->next=q->next;
            q=q->next;
        }
        else{
            q=q->next;
            p=p->next;
        }
    }
    return head;
}
int main()
{   datatype x;
    linklist head;
    head=creatbyqueue();                /*尾插入法建立带头结点的单链表*/
    print(head);
    printf("请输入要删除的值:");
    scanf("%d",&x);
    head=delallx(head,x);
    print(head);
    delList(head);
    return 0;
}

实验3.5

已知线性表存储在带头结点的单链表head中,请设计算法函数void sort(linklist head),将head中的结点按结点值升序排列。

/*
已知线性表存储在带头结点的单链表head中,请设计算法函数void sort(linklist head),将head中的结点按结点值升序排列。
*/
/**********************************/
/*文件名称:lab3_05.c                 */
/**********************************/
#include "slnklist.h"
#include<vector>
#include<iostream>
using namespace std;
/*请将本函数补充完整,并进行测试*/
void  sort(linklist head){
    vector<int> a;
    node* pp=head->next;
    while(pp){
        a.push_back(pp->info);
        pp=pp->next;
    }
    head->next=NULL;
    while(!a.empty()){
        node* pp=head;
        node* q=head->next;
        while(q){
            if(q->info>a.back()){
                node* s=(node*)malloc(sizeof(node));
                pp->next=s;
                s->info=a.back();
                s->next=q;
                a.pop_back();
                break;
            }
            else{
            pp=q;
            q=q->next;
            }   
        }
            if(!q){
                node* s=(node*)malloc(sizeof(node));
                pp->next=s;
                s->next=NULL;
                s->info=a.back();
                a.pop_back(); 
            }
    }
}
​
int main()
{        linklist head;
         head=creatbyqueue();           /*尾插法建立带头结点的单链表*/
         print(head);                   /*输出单链表head*/
         sort(head);                    /*排序*/
         print(head);
         delList(head);
         return 0;
}

实验3.6

已知两个带头结点的单链表L1和L2中的结点值均已按升序排序,设计算法函数 linklist mergeAscend (linklist L1,linklist L2)将L1和L2合并成一个升序的 带头结单链表作为函数的返回结果; 设计算法函数linklist mergeDescend (linklist L1,linklist L2) 将L1和L2合并成一个降序的带头结单链表作为函数的返回结果; 并设计main()函数进行测试。

/*
已知两个带头结点的单链表L1和L2中的结点值均已按升序排序,设计算法函数
linklist mergeAscend (linklist L1,linklist L2)将L1和L2合并成一个升序的
带头结单链表作为函数的返回结果;
设计算法函数linklist mergeDescend (linklist L1,linklist L2)
将L1和L2合并成一个降序的带头结单链表作为函数的返回结果;
并设计main()函数进行测试。
*/
/**********************************/
/*文件名称:lab3_06.c                 */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist mergeAscend(linklist L1,linklist L2)
{
    node* L3=(node*)malloc(sizeof(node));
    node* r=L3;
    node* p=L1->next,*q=L2->next;
    while(p&&q){
        if(p->info>q->info){
            node* s=(node*)malloc(sizeof(node));
            s->info=q->info;
            q=q->next;
            r->next=s;
            r=s;
        }
        else{
            node* s=(node*)malloc(sizeof(node));
            s->info=p->info;
            p=p->next;
            r->next=s;
            r=s;    
        }
    }
    while(p){
        node* s=(node*)malloc(sizeof(node));
        s->info=p->info;
        p=p->next;
        r->next=s;
        r=s;
    }   
    while(q){
        node* s=(node*)malloc(sizeof(node));
        s->info=q->info;
        q=q->next;
        r->next=s;
        r=s;
    }
    r->next=NULL;
    return L3;
}
linklist mergeDescend(linklist L1,linklist L2)
{
    node* r=NULL;
    node* L3=(node*)malloc(sizeof(node));
    node* p=L1->next,*q=L2->next;
    while(p&&q){
        if(p->info>q->info){
            node* s=(node*)malloc(sizeof(node));
            s->info=q->info;
            q=q->next;
            s->next=r;
            r=s;
        }
        else{
            node* s=(node*)malloc(sizeof(node));
            s->info=p->info;
            p=p->next;
            s->next=r;
            r=s;    
        }
    }
    while(p){
            node* s=(node*)malloc(sizeof(node));
            s->info=p->info;
            p=p->next;
            s->next=r;
            r=s;
    }   
    while(q){
            node* s=(node*)malloc(sizeof(node));
            s->info=q->info;
            q=q->next;
            s->next=r;
            r=s;
    }
    L3->next=r;
    return L3;
}
int main()
{       linklist h1,h2,h3;
         h1=creatbyqueue();     /*尾插法建立单链表,请输入升序序列*/
         h2=creatbyqueue();
         print(h1);
         print(h2);
//         h3=mergeAscend(h1,h2);/*升序合并到h3*/
         h3=mergeDescend(h1,h2); //降序合并请调用
         print(h3);
         delList(h3);
         return 0;
}

实验3.7

设计一个算法linklist interSection(linklist L1,linklist L2), 求两个单链表表示的集合L1和L2的交集,并将结果用一个新的带头 结点的单链表保存并返回表头地址。

/*
设计一个算法linklist interSection(linklist L1,linklist L2),
求两个单链表表示的集合L1和L2的交集,并将结果用一个新的带头
结点的单链表保存并返回表头地址。
*/
/**********************************/
/*文件名称:lab3_07.c                 */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist   interSection(linklist L1, linklist L2)
{
    node* L3=(node*)malloc(sizeof(node));
    node* r=L3;
    node* p=L1->next;
    while(p){
        node* q=L2->next;           
        while(q){
            if(p->info==q->info){
                node* s=(node*)malloc(sizeof(node));
                s->info=p->info;
                r->next=s;
                r=s;
                r->next=NULL; 
            }
            q=q->next;
        }
        p=p->next;
    }
    return L3;
}
int main()
{
 linklist h1,h2,h3;
 h1=creatbyqueue();           /*尾插法建立单链表,输入时请勿输入重复数据*/
 h2=creatbyqueue();
 print(h1);                   /*输出单链表h1*/
 print(h2);
 h3=interSection(h1,h2);      /* 求h1和h2的交集*/
 print(h3);
 delList(h1);
 delList(h2);
 delList(h3);
 return 0;
}

实验3.8

请编写一个算法函数void partion(linklist head), 将带头结点的单链表head中的所有值为奇数的结点调整 到链表的前面,所有值为偶数的结点调整到链表的后面。

/*
请编写一个算法函数void partion(linklist head),
将带头结点的单链表head中的所有值为奇数的结点调整
到链表的前面,所有值为偶数的结点调整到链表的后面。
*/

/**********************************/
/*文件名称:lab3_08.c             */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
void partion(linklist head)
{
	if(head->next->next&&head->next){
		node* p=head->next;
		node* q=head->next->next;
		while(q){
			if(q->info%2==1){
				p->next=p->next->next;
				q->next=head->next;
			 	head->next=q;
			 	q=p->next;
			} 	 
			else{
				p=p->next;
				q=q->next;	
			}
		}
	}

}
int main()
{        linklist head;
         head=creatbyqueue();           /*尾插法建立带头结点的单链表*/
         print(head);                   /*输出单链表head*/
         partion(head);
         print(head);
         delList(head);
         return 0;
}

实验3.9

编写一个程序,用尽可能快的方法返回带头结点单链表中倒数第k个结点的地址,如果不存在,则返回NULL。

/*
编写一个程序,用尽可能快的方法返回带头结点单链表中倒数第k个结点的地址,如果不存在,则返回NULL。
*/
/**********************************/
/*文件名称:lab3_09.c             */
/**********************************/
#include "slnklist.h"
/*请将本函数补充完整,并进行测试*/
linklist   search(linklist head,int k)
{
	int i=0;
	node* p=head;
	while(p){
		i++;
		p=p->next;
	}
	p=head;
	if(i-k<=0)
		return NULL;
	else{
		for(int j=0;j<i-k;j++){
			p=p->next;
		}	
		return p;
	}

}
int main()
{
     int k;
     linklist head,p;
     head=creatbyqueue();        /*尾插法建立带头结点的单链表*/
     print(head);                  /*输出单链表head*/
     printf("k=");
     scanf("%d",&k);
     p=search(head,k);
     if (p) printf("%d\n",p->info);
     else
         printf("Not Found!\n");
     delList(head);
     return 0;
}
  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanlangke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值