C++第2周(春)项目6 动态链表初体验

简介: 课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接  本文是为大一刚学习程序设计语言的同学体验动态链表设计的一组练习。动态链表用途广泛,必须重视,在学习数据结构及算法之前能有所体验,意义重大。  不要被貌似复杂的指针操作迷惑,这正是专业学生应该具备的思维基本功。涉及到链接如何建立的操作,

课程首页在:http://blog.csdn.net/sxhelijian/article/details/11890759,内有完整教学方案及资源链接


  本文是为大一刚学习程序设计语言的同学体验动态链表设计的一组练习。动态链表用途广泛,必须重视,在学习数据结构及算法之前能有所体验,意义重大。

  不要被貌似复杂的指针操作迷惑,这正是专业学生应该具备的思维基本功。涉及到链接如何建立的操作,在纸上画一画,想一想,道理就通了。

  作为需要用脑作的实践,由画一画的形象思维,会形成头脑中不用画也很清楚的逻辑思维,这正是能力提高的一个必经的过程。

  做不出来,就多看几遍。做出来了,其间的不顺一扫而光,其乐无穷。

  下面是正题:

  下面是一个建立动态链表的程序。阅读程序,在草稿纸上画出链表建立的过程,借此学会如何建立链表。然后改造程序,完成项目6的要求

#include  <iostream>
using namespace std;
struct Node
{
    int data;            //结点的数据
    struct Node *next;  //指向下一结点
};
Node *head=NULL;    //将链表头定义为全局变量,以便于后面操作
void make_list();   //建立链表
void out_list();    //输出链表
  
int main( )
{
    make_list();
    out_list();
    return 0;
}
void make_list()
{
    int n;
    Node *p;
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"
    cin>>n;
    while(n>0)   //输入若干正数建立链表,输入非正数时,建立过程结束
    {
        p=new Node;  //新建结点
        p->data=n;   
        p->next=head;  //新建的结点指向原先的链表头
        head=p;    //链表头赋值为新建的节点,这样,新结点总是链表头
        cin>>n;    //输入下一个数,准备建立下一个结点
    }
    return;
}
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}


【项目6-动态链表体验】

  在上面的程序基础上定义下面的函数,实现相应的功能。为简便起见,每编写一个函数,立刻在main函数中调用进行测试。

  (1)编写make_list2()函数建立链表,使建立链表时,后输入的数据,将新输入的数字对应的结点放在链表末尾。若输入为3 5 2 9 4 7 0,建立的链表为:

     

----参考解答----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list2();  //新结点始终在链表尾部
void out_list();
int main( )
{
    freopen("input.txt","r",stdin);
    make_list2();
    out_list();
    return 0;
}

void make_list2()
{
    int n;
    Node *p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        p=new Node;
        p->data=n;
        p->next=NULL;
        if(head==NULL)
            head=p;
        else
            q->next=p;
        q=p;
        cin>>n;
    }
    return;
}

//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

  ( 2 )编写函数 void search(int x) ,输出链表中是否有值为 x 的结点。

----参考解答----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list2();  //新结点始终在链表尾部
void out_list();
void search(int x);  //查找是否有值为x的结点
int main( )
{
    int x;
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list2();
    out_list();
    cin>>x;  //测试中输入一个链表中有的数字
    search(x);
    cin>>x;  //测试中输入一个链表中没有的数字
    search(x);
    return 0;
}

void make_list2()
{
    int n;
    Node *p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        p=new Node;
        p->data=n;
        p->next=NULL;
        if(head==NULL)
            head=p;
        else
            q->next=p;
        q=p;
        cin>>n;
    }
    return;
}

//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

void search(int x)
{
    //查找是否有值为x的结点
    Node *p=head;
    while(p!=NULL&&p->data!=x)
    {
        p=p->next;
    }
    if(p!=NULL)  //退出上一层循环一定是因为p->data==x
        cout<<"在链表中有值为"<<x<<"的结点"<<endl;
    else
        cout<<"在链表中没有值为"<<x<<"的结点"<<endl;
    return;
}
//补充:这个版本的search,只判断是否找到,有兴趣的同学,可以实现能输出有几个的版本
//void search(int x)还可以重定义为bool search(int x),让main函数根据返回值输出结果
//对应能输出有几个的版本,重定义为int search(int x),返回值是存在的个数,为0没有找到

  ( 3 )编写函数 delete_first_node() ,删除链表中的第一个结点。

----参考解答----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list2();  //新结点始终在链表尾部
void out_list();
void delete_first_node();  //删除第一个结点
int main( )
{
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list2();
    out_list();
    delete_first_node();
    out_list();
    return 0;
}

void make_list2()
{
    int n;
    Node *p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        p=new Node;
        p->data=n;
        p->next=NULL;
        if(head==NULL)
            head=p;
        else
            q->next=p;
        q=p;
        cin>>n;
    }
    return;
}

//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

void delete_first_node()
{
    Node *p=head;
    if (p!=NULL)
    {
        head = p->next;
        delete p;
        cout<<"删除了首结点."<<endl;
    }
    else
        {
            cout<<"空链表,不能删除."<<endl;
        }
    return;
}

  ( 4 )编写函数 delete_node(int x) ,删除结点值为 x 的结点。

----参考解答----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list2();  //新结点始终在链表尾部
void out_list();
void delete_node(int x);  //删除第一个结点
int main( )
{
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list2();
    out_list();
    delete_node(3);
    out_list();
    return 0;
}

void make_list2()
{
    int n;
    Node *p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        p=new Node;
        p->data=n;
        p->next=NULL;
        if(head==NULL)
            head=p;
        else
            q->next=p;
        q=p;
        cin>>n;
    }
    return;
}

//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

void delete_node(int x)
{
    Node *p,*q;
    if (head==NULL)
    cout<<"空链表,不能删除";
    else
    {
       //要删除的恰是首结点(不排除连续有若干个结点值为x),
       while(head!=NULL&&head->data==x)
       {
           p=head;
           head=head->next;
           delete p;
       }
       if(head!=NULL)
       {
           p=head;
           q=p->next;
           while(q!=NULL)
           {
               if(q->data==x)//q就是该删除的结点
               {
                   p->next=q->next;
                   delete q;
               }
               else     //q不该删除,继续考察下一个
               {
                   p=q;
               }
               q=p->next;  //总是p的下一个结点
           }
       }
    }
    return;
}

为充分测试,该程序运行了5次,所用的测试输入数据分别为:

5 2 9 9 7 11 3 0

3 5 2 9 9 7 11 0

3 5 2 9 3 9 7 11 0

3 5 2 9 4 9 7 11 0

3 3 3 3 3 3 3 0


  (5)编写make_list3()函数建立有序链表,使建立链表时,结点中的数据呈现升序。若输入为3 5 2 9 4 7 0,建立的链表为:

    

----参考解答----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list3();  //建立有序链表,各结点由小到大
void out_list();
int main( )
{
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list3();
    out_list();
    return 0;
}

void make_list3()
{
    int n;
    Node *t,*p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        t=new Node;
        t->data=n;
        t->next=NULL;
        if(head==NULL)   //是空链表,p作为第一个结点即可
            head=t;
        else             //插入p结点后,各结点应该保持有序
        {
            if(n<=head->data)  //新加入的结点应该为首结点
            {
                t->next=head;
                head=t;
            }
            //应该找到合适的位置后,将结点插入
            //此时,链表中至少已经有一个结点,且插入结点不是首结点
            else
            {
                p=head;
                q=p->next;   //p与q相邻,p更靠近q,插入位置将在p和q之间
                while(q!=NULL&&n>q->data)  //链表没有完且p结点比n小,一直往后找
                {
                    p=q;
                    q=p->next;
                }
                if(q==NULL) //q为null,作为最后一个结点直接插入到p后即可
                {
                    p->next = t;
                }
                else   //t插入到p和q之间
                {
                    t->next=q;
                    p->next=t;
                }
            }
       }
        cin>>n;
    }
    return;
}

//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

  ( 6 )编写函数 void insert(int x) ,将值为 x 的结点插入到由 make_list3 建立起来的有序链表中。

----参考解答1----

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list3();  //建立有序链表,各结点由小到大
void out_list();
void insert(int x); //将值为x的结点插入到有序链表中,使仍有序
int main( )
{
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list3();
    out_list();
    insert(15);
    out_list();
    return 0;
}

void make_list3()
{
    int n;
    Node *t,*p,*q;  //p用于指向新建立的结点, q指向链表尾部
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        t=new Node;
        t->data=n;
        t->next=NULL;
        if(head==NULL)   //是空链表,p作为第一个结点即可
            head=t;
        else             //插入p结点后,各结点应该保持有序
        {
            if(n<=head->data)  //新加入的结点应该为首结点
            {
                t->next=head;
                head=t;
            }
            //应该找到合适的位置后,将结点插入
            //此时,链表中至少已经有一个结点,且插入结点不是首结点
            else
            {
                p=head;
                q=p->next;   //p与q相邻,p更靠近q,插入位置将在p和q之间
                while(q!=NULL&&n>q->data)  //链表没有完且p结点比n小,一直往后找
                {
                    p=q;
                    q=p->next;
                }
                if(q==NULL) //q为null,作为最后一个结点直接插入到p后即可
                {
                    p->next = t;
                }
                else   //t插入到p和q之间
                {
                    t->next=q;
                    p->next=t;
                }
            }
        }
        cin>>n;
    }
    return;
}

void insert(int x) //将值为x的结点插入到有序链表中,使仍有序
{
    Node *t,*p,*q;  //p用于指向新建立的结点, q指向链表尾部
    t=new Node;
    t->data=x;
    t->next=NULL;
    if(head==NULL)   //是空链表,p作为第一个结点即可
        head=t;
    else             //插入p结点后,各结点应该保持有序
    {
        if(x<=head->data)  //新加入的结点应该为首结点
        {
            t->next=head;
            head=t;
        }
        //应该找到合适的位置后,将结点插入
        //此时,链表中至少已经有一个结点,且插入结点不是首结点
        else
        {
            p=head;
            q=p->next;   //p与q相邻,p更靠近q,插入位置将在p和q之间
            while(q!=NULL&&x>q->data)  //链表没有完且p结点比n小,一直往后找
            {
                p=q;
                q=p->next;
            }
            if(q==NULL) //q为null,作为最后一个结点直接插入到p后即可
            {
                p->next = t;
            }
            else   //t插入到p和q之间
            {
                t->next=q;
                p->next=t;
            }
        }
    }
    return;
}


//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}

----参考解答2----

  实际上,从程序整体上看,makelist3()可以直接调用insert(int x)实现,这样写出的程序合乎工程上的原则。这启示我们,用函数组织程序结构,应该成为一种意识。

#include <iostream>
#include <cstdio>
using namespace std;
struct Node
{
    int data;
    struct Node *next;
};
Node *head=NULL;
void make_list3();  //建立有序链表,各结点由小到大
void out_list();
void insert(int x); //将值为x的结点插入到有序链表中,使仍有序
int main( )
{
    freopen("input.txt","r",stdin);//调试中用重定向方便
    make_list3();
    out_list();
    insert(15);
    out_list();
    return 0;
}

void make_list3()
{
    int n;
    cout<<"输入若干正数(以0或一个负数结束)建立链表:"<<endl;
    cin>>n;
    while(n>0)
    {
        insert(n);//调用insert,makelist简单得不得了
        cin>>n;
    }
    return;
}

void insert(int x) //将值为x的结点插入到有序链表中,使仍有序
{
    Node *t,*p,*q;  //p用于指向新建立的结点, q指向链表尾部
    t=new Node;
    t->data=x;
    t->next=NULL;
    if(head==NULL)   //是空链表,p作为第一个结点即可
        head=t;
    else             //插入p结点后,各结点应该保持有序
    {
        if(x<=head->data)  //新加入的结点应该为首结点
        {
            t->next=head;
            head=t;
        }
        //应该找到合适的位置后,将结点插入
        //此时,链表中至少已经有一个结点,且插入结点不是首结点
        else
        {
            p=head;
            q=p->next;   //p与q相邻,p更靠近q,插入位置将在p和q之间
            while(q!=NULL&&x>q->data)  //链表没有完且p结点比n小,一直往后找
            {
                p=q;
                q=p->next;
            }
            if(q==NULL) //q为null,作为最后一个结点直接插入到p后即可
            {
                p->next = t;
            }
            else   //t插入到p和q之间
            {
                t->next=q;
                p->next=t;
            }
        }
    }
    return;
}


//输出所有的节点
void out_list()
{
    Node *p=head;
    cout<<"链表中的数据为:"<<endl;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->next;
    }
    cout<<endl;
    return;
}



 



==================== 迂者 贺利坚 CSDN博客专栏=================

|==  IT学子成长指导专栏  专栏文章分类目录(不定期更新)    ==|

|== C++ 课堂在线专栏   贺利坚课程教学链接(分课程年级)   ==|

======== 为IT菜鸟起飞铺跑道,和学生一起享受快乐和激情的大学 =======



目录
相关文章
|
6月前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
213 7
WK
|
10天前
|
机器学习/深度学习 人工智能 算法
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
32 1
|
29天前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
237 3
|
1月前
|
存储 编译器 C++
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
【C++篇】引领C++模板初体验:泛型编程的力量与妙用
38 2
|
2月前
|
C++
【C++案例】一个项目掌握C++基础-通讯录管理系统
这篇文章通过一个通讯录管理系统的C++项目案例,详细介绍了如何使用C++实现添加、显示、删除、查找、修改和清空联系人等功能。
39 3
|
4月前
|
Rust 测试技术 编译器
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
|
3月前
|
编译器 C++ 开发者
Visual Studio属性表:在新项目中加入已配置好的C++库
通过以上步骤可以确保Visual Studio中新项目成功地加入了之前已配置好的C++库。这个过程帮助开发者有效地管理多个项目中共享的库文件,提升开发效率。
81 0
|
4月前
|
存储 C++
C++的list-map链表与映射表
```markdown C++ 中的`list`和`map`提供链表和映射表功能。`list`是双向链表,支持头尾插入删除(`push_front/push_back/pop_front/pop_back`),迭代器遍历及任意位置插入删除。`map`是键值对集合,自动按键排序,支持直接通过键来添加、修改和删除元素。两者均能使用范围for循环遍历,`map`的`count`函数用于统计键值出现次数。 ```
|
5月前
|
存储 C++
C++的list-map链表与映射表
这篇教程介绍了C++中`list`链表和`map`映射表的基本使用。`list`链表可通过`push_front()`、`push_back()`、`pop_front()`和`pop_back()`进行元素的添加和删除,使用迭代器遍历并支持在任意位置插入或删除元素。`map`是一个键值对的集合,元素自动按键值排序,可使用下标操作符或`insert()`函数插入元素,通过迭代器遍历并修改键值对,同时提供`count()`方法统计键值出现次数。教程中包含多个示例代码以帮助理解和学习。
|
4月前
|
Java C++ 开发者
如何根据项目需求选择使用C++还是Python进行内存管理?
【7月更文挑战第2天】如何根据项目需求选择使用C++还是Python进行内存管理?
47 0
下一篇
无影云桌面