数据结构链表(单链表)

目录

结点的定义

链表的操作

链表的前插

链表的后插

链表的初始化

链表的取值

链表的查找

链表的插入

链表的删除

删除链表中的重复元素

链表排序(升序和降序)

合并两个升序的链表

反转链表

销毁链表

链表的遍历

链表的实现

.h文件

.cpp文件

main.cpp文件

运行试例

欢迎指正


结点的定义

重定义elemtype为新的数据类型,用法与int相同。这可以方便修改链表的数据域,只需要修改重定义即可。

typedef int elemtype;

下面是结点的基本结构

typedef struct m{
    elemtype n;
    struct m *next;
}list,*plist;

链表的操作

选择带头结点的链表方便对链表进行操作。

链表的前插

void createlist_h(plist &l,int n)//前插n个元素
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //定义一个指针t,初始值为空
    plist t;
    //定义一个变量i,初始值为0
    int i;
    //当i小于n时,循环执行以下操作
    for(i=0;i<n;i++)
    {
        //定义一个新节点
        t=new list;
        //输入新节点的值
        cin>>t->n;
        //将新节点的指针指向头指针的下一个节点
        t->next=l->next;
        //将头指针的下一个节点指向新节点
        l->next=t;
    }
}

链表的后插

void createlist_r(plist &l,int n)//后插n个元素
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //定义一个指针t,初始值为l
    plist t,r=l;
    //定义一个变量i,初始值为0
    int i;
    //当i小于n时,循环执行以下操作
    for(i=0;i<n;i++)
    {
        //定义一个新节点
        t=new list;
        //输入新节点的值
        cin>>t->n;
        //将新节点的指针指向r的下一个节点
        t->next=r->next;
        //将r的下一个节点指向新节点
        r->next=t;
        t->next=NULL;
        r=t;
    }
}

链表的初始化

bool initlist(plist &l)//初始化带头结点的链表
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //返回1
    return 1;
}

链表的取值

bool getelem(plist l,int i,elemtype &e)//取出第i个结点的数据赋值给e
{
    //定义变量j,初始值为1
    int j=1;
    //定义变量p,初始值为l的下一个节点
    plist p=l->next;
    //当j小于i,且p不为空时,循环执行以下操作
    while(j<i&&p)
    {    
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    //当p为空,或者j大于i时,返回0
    if(!p||j>i)return 0;
    //将p的值赋给e
    e=p->n;
    //返回1
    return 1;
}

链表的查找

plist locatelem(plist l,elemtype e)//查找值为e的结点
{
    //定义一个指针p,初始值为l的下一个节点
    plist p=l->next;
    //当p不为空,且p的下一个节点为空时,循环执行以下操作
    while(p&&!p->next)
        p=p->next;
    //返回p
    return p;
}

链表的插入

bool listinsert(plist &l,int i,elemtype e)//在第i个结点前插入元素e
{
    //定义一个指针p,初始值为l
    plist p=l,t=new list;
    //定义一个变量j,初始值为0
    int j=0;
    //当p不为空,且j小于i-1时,循环执行以下操作
    while(p&&j<i-1)
    {
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    if(!p&&j>i-1)return 0;
    //当p为空,或者j大于i-1时,返回0
    if(!p||j>i-1)return 0;
    //将e赋给t
    t->n=e;
    //将t的指针指向p的下一个节点
    t->next=p->next;
    //将p的指针指向t
    p->next=t;
    //返回1
    return 1;
}

链表的删除

bool listdelete(plist &l,int i)//删除第i个元素
{
    //定义一个指针p,初始值为l
    plist p=l,t;
    //定义一个变量j,初始值为0
    int j=0;
    //当p的下一个节点不为空,且j小于i-1时,循环执行以下操作
    while(p->next&&j<i-1)
    {
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    //当p的下一个节点为空,或者j大于i-1时,返回0
    if(!p->next||j>i-1)return 0;
    //将p的指针指向下一个节点
    t=p->next;
    //将t的指针指向空
    p->next=t->next;
    //删除t
    delete t;
    //返回1
    return 1;
}

删除链表中的重复元素

void ddlist(plist &l)//删除链表中的重复元素
{
    //p指向当前节点,t指向下一个节点
    plist p=l->next,t,t1,m;
    while(p)
    {
        //t指向下一个节点
        t=p->next;
        //t1指向当前节点
        t1=p;
        //m指向当前节点
        while(t)
        {
            //如果当前节点和下一个节点值相同
            if(p->n==t->n)
            {
                //m指向下一个节点
                m=t;
                //t指向下一个节点
                t=t->next;
                //将当前节点指向下一个节点
                t1->next=t;
                //删除m指向的节点
                delete m;
            }
            else {
                //t1指向下一个节点
                t1=t;
                //t指向下一个节点
                t=t->next;
            }
        }
        //p指向下一个节点
        p=p->next;
    }
}

链表排序(升序和降序)

void sortlist(plist &l,int i)//链表排序
{
    //定义一个指针p指向当前节点,初始值为l的下一个节点
    plist p=l->next,t;
    elemtype m;
    if(i==0)//升序
    while(p)
    {
        //定义一个指针t指向当前节点的下一个节点
        t=p->next;
        //当t不为空时,循环比较p和t的n值
        while(t)
        {
            //如果p的n值大于t的n值,交换p和t的n值
            if(p->n>t->n)
            {
                m=p->n;
                p->n=t->n;
                t->n=m;
            }
            else t=t->next;
            //t指向t的下一个节点
        }
        //p指向p的下一个节点
        p=p->next;
    }
    else if(i==1)//降序
    while(p)
    {
        //定义一个指针t指向当前节点的下一个节点
        t=p->next;
        //当t不为空时,循环比较p和t的n值
        while(t)
        {
            //如果p的n值小于t的n值,交换p和t的n值
            if(p->n<t->n)
            {
                m=p->n;
                p->n=t->n;
                t->n=m;
            }
            else t=t->next;
            //t指向t的下一个节点
        }
        //p指向p的下一个节点
        p=p->next;
    }
    //显示链表
    display(l);
}

合并两个升序的链表

plist mergelist(plist l,plist i)//合并两个升序的链表
{
    // l: 第一个链表,i: 第二个链表
    plist p=l->next,t=i->next,l1,l2;
    // p: 第一个链表的指针,t: 第二个链表的指针,l1: 合并后的链表,l2: 合并后的链表的指针
    initlist(l1);
    // 初始化合并后的链表
    l2=l1;
    // l2: 合并后的链表的指针
    while(p&&t)
    {
        // 当两个链表都不为空时
        if(p->n<=t->n)
        {
            // 如果第一个链表的指针的值小于等于第二个链表的指针的值
            l2->next=p;
            // 将第一个链表的指针的值赋值给l2的指针的下一个值
            p=p->next;
            // 将第一个链表的指针的值指向下一个值
            l2=l2->next;
            // 将l2的指针的值指向下一个值
            l2->next=NULL;
            // 将l2的指针的值指向空
        }
        else 
        {
            // 如果第一个链表的指针的值大于第二个链表的指针的值
            l2->next=t;
            // 将第二个链表的指针的值赋值给l2的指针的下一个值
            t=t->next;
            // 将第二个链表的指针的值指向下一个值
            l2=l2->next;
            // 将l2的指针的值指向下一个值
            l2->next=NULL;
            // 将l2的指针的值指向空
        }
    }
    if(!p)l2->next=t;
    // 如果第一个链表的指针为空,将第二个链表的指针的值赋值给l2的指针的下一个值
    else l2->next=p;
    // 将第一个链表的指针的值赋值给l2的指针的下一个值
    return l1;
    // 返回合并后的链表
}

反转链表

void imagelist(plist &l)//反转链表
{
    plist p,t,t1,q=l->next;
    while(q->next)q=q->next;//q指向最后一个结点,作为反转后的首元结点
    while(1)
    {
        p=t=l->next;
        while(t->next)//t指向当前链表的最后一个结点
        {
            t1=t;
            t=t->next;
        }
        t->next=t1;//t之前倒数第二个结点
        t1->next=NULL;//将t剔除
        t=t->next;//t指向新链表的最后一个结点
        if(t==p)break;
    }
    l->next=q;//l的头结点指向q
}

销毁链表

void breaklist(plist &l)//销毁链表
{
    // l: 链表
    plist p=l->next,t;
    // p: 链表的指针,t: 链表的指针
    while(p)
    {
        t=p;
        p=p->next;
        delete t;
        // 删除链表的指针的值指向的值
    }
    delete l;
    // 销毁链表
}

链表的遍历

void display(plist l)
{
    //定义一个指针p,初始值为l的下一个节点
    plist p=l->next;
    //当p不为空时,循环执行以下操作
    while(p)
    {
        //输出p的值
        cout<<p->n<<" ";
        //将p指向下一个节点
        p=p->next;
    }
    //换行
    cout<<endl;
}

链表的实现

我用项目的方法进行实现。项目的建立可以参考我的博客

.h文件

#include<iostream>
using namespace std;
typedef int elemtype;
typedef struct m{
    elemtype n;
    struct m *next;
}list,*plist;
void menu();//菜单
void createlist_h(plist &l,int n);//前插n个元素
void createlist_r(plist &l,int n);//后插n个元素
bool initlist(plist &l);//初始化带头结点的链表
bool getelem(plist l,int i,elemtype &e);//取出第i个结点的数据赋值给e
plist locatelem(plist l,elemtype e);//查找值为e的结点
bool listinsert(plist &l,int i,elemtype e);//在第i个结点前插入元素e
bool listdelete(plist &l,int i);//删除第i个元素
void display(plist l);//显示链表
void ddlist(plist &l);//删除链表中的重复元素
void sortlist(plist &l,int i);//链表排序
plist mergelist(plist l,plist i);//合并两个升序的链表
void imagelist(plist &l);//反转链表
void breaklist(plist &l);//销毁链表

.cpp文件

#include"own.h"
void menu()//菜单
{
    cout<<"1.取值       2.查找  3.插入    4.删除"<<endl;
    cout<<"5.显示元素   6.删除重复元素     7.排序"<<endl;
    cout<<"8.合并两个升序的链表     9.反转链表  -1.退出"<<endl;
    cout<<"请输入:"<<endl;
}
void createlist_h(plist &l,int n)//前插n个元素
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //定义一个指针t,初始值为空
    plist t;
    //定义一个变量i,初始值为0
    int i;
    //当i小于n时,循环执行以下操作
    for(i=0;i<n;i++)
    {
        //定义一个新节点
        t=new list;
        //输入新节点的值
        cin>>t->n;
        //将新节点的指针指向头指针的下一个节点
        t->next=l->next;
        //将头指针的下一个节点指向新节点
        l->next=t;
    }
}
void createlist_r(plist &l,int n)//后插n个元素
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //定义一个指针t,初始值为l
    plist t,r=l;
    //定义一个变量i,初始值为0
    int i;
    //当i小于n时,循环执行以下操作
    for(i=0;i<n;i++)
    {
        //定义一个新节点
        t=new list;
        //输入新节点的值
        cin>>t->n;
        //将新节点的指针指向r的下一个节点
        t->next=r->next;
        //将r的下一个节点指向新节点
        r->next=t;
        t->next=NULL;
        r=t;
    }
}
bool initlist(plist &l)//初始化带头结点的链表
{
    //定义一个带头结点的链表
    l=new list;
    //将头指针的下一个节点指向空
    l->next=NULL;
    //返回1
    return 1;
}
bool getelem(plist l,int i,elemtype &e)//取出第i个结点的数据赋值给e
{
    //定义变量j,初始值为1
    int j=1;
    //定义变量p,初始值为l的下一个节点
    plist p=l->next;
    //当j小于i,且p不为空时,循环执行以下操作
    while(j<i&&p)
    {    
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    //当p为空,或者j大于i时,返回0
    if(!p||j>i)return 0;
    //将p的值赋给e
    e=p->n;
    //返回1
    return 1;
}
plist locatelem(plist l,elemtype e)//查找值为e的结点
{
    //定义一个指针p,初始值为l的下一个节点
    plist p=l->next;
    //当p不为空,且p的下一个节点为空时,循环执行以下操作
    while(p&&!p->next)
        p=p->next;
    //返回p
    return p;
}
bool listinsert(plist &l,int i,elemtype e)//在第i个结点前插入元素e
{
    //定义一个指针p,初始值为l
    plist p=l,t=new list;
    //定义一个变量j,初始值为0
    int j=0;
    //当p不为空,且j小于i-1时,循环执行以下操作
    while(p&&j<i-1)
    {
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    if(!p&&j>i-1)return 0;
    //当p为空,或者j大于i-1时,返回0
    if(!p||j>i-1)return 0;
    //将e赋给t
    t->n=e;
    //将t的指针指向p的下一个节点
    t->next=p->next;
    //将p的指针指向t
    p->next=t;
    //返回1
    return 1;
}
bool listdelete(plist &l,int i)//删除第i个元素
{
    //定义一个指针p,初始值为l
    plist p=l,t;
    //定义一个变量j,初始值为0
    int j=0;
    //当p的下一个节点不为空,且j小于i-1时,循环执行以下操作
    while(p->next&&j<i-1)
    {
        //将p指向下一个节点
        p=p->next;
        //将j加1
        j++;
    }
    //当p的下一个节点为空,或者j大于i-1时,返回0
    if(!p->next||j>i-1)return 0;
    //将p的指针指向下一个节点
    t=p->next;
    //将t的指针指向空
    p->next=t->next;
    //删除t
    delete t;
    //返回1
    return 1;
}
void display(plist l)
{
    cout<<"该链表为:";
    //定义一个指针p,初始值为l的下一个节点
    plist p=l->next;
    //当p不为空时,循环执行以下操作
    while(p)
    {
        //输出p的值
        cout<<p->n<<" ";
        //将p指向下一个节点
        p=p->next;
    }
    //换行
    cout<<endl;
}
void ddlist(plist &l)//删除链表中的重复元素
{
    //p指向当前节点,t指向下一个节点
    plist p=l->next,t,t1,m;
    while(p)
    {
        //t指向下一个节点
        t=p->next;
        //t1指向当前节点
        t1=p;
        //m指向当前节点
        while(t)
        {
            //如果当前节点和下一个节点值相同
            if(p->n==t->n)
            {
                //m指向下一个节点
                m=t;
                //t指向下一个节点
                t=t->next;
                //将当前节点指向下一个节点
                t1->next=t;
                //删除m指向的节点
                delete m;
            }
            else {
                //t1指向下一个节点
                t1=t;
                //t指向下一个节点
                t=t->next;
            }
        }
        //p指向下一个节点
        p=p->next;
    }
}
void sortlist(plist &l,int i)//链表排序
{
    //定义一个指针p指向当前节点,初始值为l的下一个节点
    plist p=l->next,t;
    elemtype m;
    if(i==0)//升序
    while(p)
    {
        //定义一个指针t指向当前节点的下一个节点
        t=p->next;
        //当t不为空时,循环比较p和t的n值
        while(t)
        {
            //如果p的n值大于t的n值,交换p和t的n值
            if(p->n>t->n)
            {
                m=p->n;
                p->n=t->n;
                t->n=m;
            }
            else t=t->next;
            //t指向t的下一个节点
        }
        //p指向p的下一个节点
        p=p->next;
    }
    else if(i==1)//降序
    while(p)
    {
        //定义一个指针t指向当前节点的下一个节点
        t=p->next;
        //当t不为空时,循环比较p和t的n值
        while(t)
        {
            //如果p的n值小于t的n值,交换p和t的n值
            if(p->n<t->n)
            {
                m=p->n;
                p->n=t->n;
                t->n=m;
            }
            else t=t->next;
            //t指向t的下一个节点
        }
        //p指向p的下一个节点
        p=p->next;
    }
    //显示链表
    display(l);
}
plist mergelist(plist l,plist i)//合并两个升序的链表
{
    // l: 第一个链表,i: 第二个链表
    plist p=l->next,t=i->next,l1,l2;
    // p: 第一个链表的指针,t: 第二个链表的指针,l1: 合并后的链表,l2: 合并后的链表的指针
    initlist(l1);
    // 初始化合并后的链表
    l2=l1;
    // l2: 合并后的链表的指针
    while(p&&t)
    {
        // 当两个链表都不为空时
        if(p->n<=t->n)
        {
            // 如果第一个链表的指针的值小于等于第二个链表的指针的值
            l2->next=p;
            // 将第一个链表的指针的值赋值给l2的指针的下一个值
            p=p->next;
            // 将第一个链表的指针的值指向下一个值
            l2=l2->next;
            // 将l2的指针的值指向下一个值
            l2->next=NULL;
            // 将l2的指针的值指向空
        }
        else 
        {
            // 如果第一个链表的指针的值大于第二个链表的指针的值
            l2->next=t;
            // 将第二个链表的指针的值赋值给l2的指针的下一个值
            t=t->next;
            // 将第二个链表的指针的值指向下一个值
            l2=l2->next;
            // 将l2的指针的值指向下一个值
            l2->next=NULL;
            // 将l2的指针的值指向空
        }
    }
    if(!p)l2->next=t;
    // 如果第一个链表的指针为空,将第二个链表的指针的值赋值给l2的指针的下一个值
    else l2->next=p;
    // 将第一个链表的指针的值赋值给l2的指针的下一个值
    return l1;
    // 返回合并后的链表
}
void imagelist(plist &l)//反转链表
{
    plist p,t,t1,q=l->next;
    while(q->next)q=q->next;//q指向最后一个结点,作为反转后的首元结点
    while(1)
    {
        p=t=l->next;
        while(t->next)//t指向当前链表的最后一个结点
        {
            t1=t;
            t=t->next;
        }
        t->next=t1;//t之前倒数第二个结点
        t1->next=NULL;//将t剔除
        t=t->next;//t指向新链表的最后一个结点
        if(t==p)break;
    }
    l->next=q;//l的头结点指向q
}
void breaklist(plist &l)//销毁链表
{
    // l: 链表
    plist p=l->next,t;
    // p: 链表的指针,t: 链表的指针
    while(p)
    {
        t=p;
        p=p->next;
        delete t;
        // 删除链表的指针的值指向的值
    }
    delete l;
    // 销毁链表
}

main.cpp文件

#include"own.h"
int main()
{
    //定义变量
    int n,a;
    plist h,h1;
    //循环输入
    while(1)
    {
        cout<<"1.前插   2.后插"<<endl;
        cout<<"请输入:";
        cin>>a;
        cout<<"请输入元素个数:";
        cin>>n;
        cout<<"请输入元素:";
        //根据输入的选项,调用不同的函数
        if(a==1){
            createlist_h(h,n);
            break;
        }
        else if(a==2){
            createlist_r(h,n);
            break;
        }
    }
    //循环输出
    while(1)
    {
        menu();
        cin>>a;
        //根据输入的选项,调用不同的函数
        if(a==1)
        {
            elemtype t;
            int m;
            cout<<"输入取出的元素位置:";
            cin>>m;
            //调用函数,获取元素
            if(getelem(h,m,t))
                cout<<"该元素为:"<<t<<endl;
            else cout<<"ERROR"<<endl;
        }
        else if(a==2)
        {
            plist t;
            elemtype m;
            cout<<"输入要查找元素:";
            cin>>m;
            //调用函数,查找元素
            t=locatelem(h,m);
            if(t==NULL)cout<<"ERROR"<<endl;
            else cout<<"成功"<<endl;
        }
        else if(a==3)
        {
            int m;
            elemtype t;
            cout<<"输入插入的位置和数据";
            cin>>m>>t;
            //调用函数,插入元素
            if(listinsert(h,m,t))
                cout<<"插入成功"<<endl;
            else cout<<"ERROR"<<endl;
        }
        else if(a==4)
        {
            int m;
            cout<<"请输入删除的元素位置:";
            cin>>m;
            //调用函数,删除元素
            if(listdelete(h,m))
                cout<<"删除成功"<<endl;
            else cout<<"ERROR"<<endl;
        }
        //调用函数,显示链表
        if(a==5)display(h);
        if(a==6)
        {
            ddlist(h);
            display(h);
        }
        if(a==7)
        {
            int i;
            cout<<"0.升序   1.降序"<<endl;
            cin>>i;
            sortlist(h,i);
        }
        if(a==8)
        {
            plist t;
            initlist(h1);
            cout<<"h1尾插五个:";
            createlist_r(h1,5);
            h=mergelist(h,h1);
            display(h);
        }
        if(a==9)
        {
            imagelist(h);
            display(h);
        }
        else if(a==-1)break;
    }
    if(h)breaklist(h);
    if(h1)breaklist(h1);
}

运行试例

4d1f3dcf4dec40b7afe91430c4542aef.png

93a941ba04a74ffbb0dba4119733dc4a.png

欢迎指正

感谢阅读本文,如果您有任何问题或建议,请随时与我联系。祝愿您编程愉快,继续前进!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晓零清

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

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

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

打赏作者

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

抵扣说明:

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

余额充值