单链表

前面是基本操作,后面是附加题
main.cpp

#include <iostream>
#include "SList.h"
using namespace std;

int main()
{
    LinkList mylist;
    InitLinkList(&mylist);
    ElemType Item;
    LNode *p;
    int pos;

    int select =1;
    while(select)
    {
        printf("********************单链表基本操作**************************\n");
        printf("**[1]前端插入元素************************[2]后端插入元素****\n");
        printf("**[3]显示数据元素************************[4]后端删除元素****\n");
        printf("**[5]前端删除元素************************[6]显示链表长度****\n");
        printf("**[7]按位置插入元素**********************[8]按值删除元素**\n");
        printf("**[9]排序********************************[10]逆置链表*******\n");
        printf("**[11]查找元素所在位置*******************[12]清空链表*******\n");
        printf("**[13]查找链表中大于x的元素个数**********[14]***************\n");

        printf("请选择:>>\n");
        scanf("%d",&select);
        if(select ==0)
            break;
        switch(select)
        {
        case 1:
            printf("输入元素的值,以-1为结束标志。\n");
            while(scanf("%d",&Item),Item!=-1)
            {
                push_front(&mylist,Item);
            }
            break;
        case 2:

            printf("输入元素的值,以-1为结束标志。\n");
            while(scanf("%d",&Item),Item!=-1)
            {
                push_back(&mylist,Item);
            }
            break;
        case 3:
            showList(&mylist);
            break;
        case 4:
            pop_back(&mylist);
            break;
        case 5:
            pop_front(&mylist);
            break;
        case 6:
            printf("链表长度为:%d\n",length_list(&mylist));
            break;
        case 7:
            printf("请输入要插入元素的值:\n");
            scanf("%d",&Item);
            printf("请输入要插入元素的位置:\n");
            scanf("%d",&pos);
            insertLinklist_pos(&mylist,pos,Item);
            break;
        case 8:
            printf("请输入要删除元素的值:\n");
            scanf("%d",&Item);
            delete_LinkList_val(&mylist,Item);
            break;
        case 9:
            sortLinkList(&mylist);
            break;
        case 10:
            reverseLinkList(&mylist);
            break;
        case 11:
            printf("请输入要查找元素的值:\n");
            scanf("%d",&Item);
            pos=findval_val(&mylist,Item);
            if(pos==-1)
                printf("没有该元素!\n");
            else
                printf("%d的位置为:%d\n",Item,pos);
            break;
        case 12:
            clearLinkList(&mylist);
            break;
        case 13:
            printf("请输入x的值:\n");
            scanf("%d",&Item);
            printf("链表中大于%d的元素个数为:%d\n",Item,countX(&mylist,Item));
            break;


        default:
            printf("输入错误,请重新输入!\n");
            break;

        }
    }
    destroyLinkList(&mylist); //销毁链表

    return 0;
}

SList.h

#ifndef SLIST_H_INCLUDED
#define SLIST_H_INCLUDED
#include <stdio.h>
#include <assert.h>
#include <malloc.h>

typedef int ElemType;  //定义类型

typedef struct LNode  //定义结点
{
    ElemType data;   //数据域
    struct LNode *next;  //指向后继结点的指针域
}LNode,*PNode;  //PNode为节点类型指针

typedef struct LinkList  //定义链表
{
    PNode first;  //头指针
    PNode last;  //尾指针
    int list_size;  //链表中有效元素个数
}LinkList;


int countX(LinkList *list,ElemType x); 统计大于某个值的节点个数//
/基本操作/
void InitLinkList(LinkList *list);//初始化链表
LNode *_buyNode(ElemType Item);//新增结点
void push_front(LinkList *list,ElemType x);//向链表中头插结点
void push_back(LinkList *list,ElemType x);//向链表中尾插结点
void showList(LinkList *list);//显示链表元素
void pop_back(LinkList *list);//尾部删除结点
void pop_front(LinkList *list);//头部删除节点
int length_list(LinkList *list);//返回链表长度
void insertLinklist_pos(LinkList *list,int pos,ElemType key);//按照pos指定的位置插入元素
void delete_LinkList_val(LinkList *list,ElemType x);//删除第一个值为x的元素
void sortLinkList(LinkList *list); //排序
void reverseLinkList(LinkList *list);//逆置链表元素
void clearLinkList(LinkList *list);//清空单链表
void destroyLinkList(LinkList *list);//销毁单链表
int findval_val(LinkList *list,ElemType key);//查找链表中首个值为key的元素位置
#endif // SLIST_H_INCLUDED

SList.cpp

#include "SList.h"

int countX(LinkList *list,ElemType x) 统计大于某个值的节点个数//
{
    LNode *p=list->first->next;
    int n=0;
    while(p!=NULL)
    {
        if(p->data>x)
            n++;
        p=p->next;
    }
    return n;
}



void InitLinkList(LinkList *list) //初始化链表
{
    LNode *head=(LNode *)malloc(sizeof(LNode));//定义头节点
    assert(head!=NULL);  //断言空间是否分配成功
    head->next=NULL;  //将头节点指针域设置为空
    list->first=list->last=head;  //初始化链表中的头指针、尾指针
    list->list_size=0;//初始化链表的长度
}
LNode *_buyNode(ElemType x)//新增结点,注意:返回的是新增节点的指针
{
    LNode *s;
    s=(LNode *)malloc(sizeof(LNode));
    assert(s!=NULL);
    s->data=x;
    s->next=NULL;
    return s;
}
void push_front(LinkList *list,ElemType x) //向链表中头插结点
{
    LNode *s;
    s=(LNode *)malloc(sizeof(LNode));
    assert(s!=NULL);
    s->data=x;
    //s->next=NULL;
    if(list->list_size==0)//注意:若插入元素为第一个元素。则需要修改尾指针指向的位置
    {
        list->last=s;
    }
    s->next=list->first->next;
    list->first->next=s;
    list->list_size++;//链表长度加1
}
void push_back(LinkList *list,ElemType x) //向链表中尾插结点
{
    LNode *s;
    s=_buyNode(x);
    list->last->next=s;
    list->last=s;
    list->list_size++;
}
void showList(LinkList *list) //显示链表元素
{
    LNode *p;
    p=list->first->next;
    while(p!=NULL)
    {
        printf("%d->",p->data);
        p=p->next;
    }
    printf("Nul.\n");
}
void pop_back(LinkList *list) //尾部删除结点
{
        //判断是否是空表
        if(list->list_size==0)
            return;
        LNode *p=list->first;
        while(p->next!=list->last)//找到倒数第二个结点
        {
            p=p->next;
        }
        //删除最后一个结点,并重新定位尾指针
        free(list->last);
        p->next=NULL;
        list->last=p;
        list->list_size--;//表的长度减一
}
void pop_front(LinkList *list) //头部删除节点
{
    if(list->list_size==0)//判断表是否为空
        return;
    LNode *p=list->first->next;
    list->first->next=p->next;//断开第一个结点的指针
    if(p->next==NULL)  如果只有一个元素,需修改尾指针p为最后一个元素
    {
        list->last=list->first;
    }

    free(p);
    list->list_size--;
}
int length_list(LinkList *list) //返回链表长度
{
    return list->list_size;
}

void insertLinklist_pos(LinkList *list,int pos,ElemType key)//按照pos指定的位置插入元素
{
    if(pos<1 || pos>list->list_size+1)
    {
        printf("输入位置不合理。\n");
        return;
    }
    LNode *s=_buyNode(key);
    LNode *p=list->first;
    for(int i=1;i<pos;i++)//将p定位到要插入位置的前一个结点
    {
        p=p->next;
    }
    s->next=p->next;
    p->next=s;
    list->list_size++;
}
void delete_LinkList_val(LinkList *list,ElemType x)//删除第一个值为x的元素
{
    if(list->list_size==0)
        return;
    LNode *p=list->first;
    //将p定位到要删除节点的前一个结点
    while(p->next!=NULL && p->next->data!=x  )//注意p!=NULL必须在前面
    {
        p=p->next;
    }

    if(p->next==NULL)//没找到
        {
            printf("表中没有值为%d的元素。\n",x);
            return;
        }
    else if(p->next==list->last)//如果要删除的节点为最后一个节点
        pop_back(list);
    else//找到后,删除p后面的节点
    {
        LNode *q=p->next;
        p->next=q->next;
        free(q);
    }
    list->list_size--;
}

void sortLinkList(LinkList *list) //排序
{
   if(list->list_size==0)
    return;
   LNode *p,*q,*s;
   //首元素结点之后断开
   p=list->first->next;
   q=p->next;//q记录断开后的节点地址
   p->next=NULL;
   list->last=p;//重新定为尾指针
   while(q!=NULL)  //依次扫描剩余结点
   {
       p=q;
       q=q->next;//重新定位p、q的位置,p指向剩余结点中每轮要插入的结点。q执行p的下一个节点

       s=list->first;//s指向待排序链表的头节点
       while(s->next!=NULL && s->next->data<p->data)
       {
           //如果s所指的下一个结点小于要插入的p所指结点,则s向后移动

           s=s->next;
       }
       //跳出循环后,s所指的下一个结点值大于p所指节点,则将p插在s之后

       if(s->next==NULL)//注意:如果插入的位置为最后一个节点,则修改尾指针位置
       {
           list->last=p;
       }
       //将p插在s之后
       p->next=s->next;
       s->next=p;
   }



}
void reverseLinkList(LinkList *list)//逆置链表元素
{
    if(list->list_size==0 || list->list_size==1)
        return;
    //将链表从第一个结点后断开,然后将其余节点前插
    LNode *p,*q,*s;
    p=list->first->next;
    q=p->next;
    list->last=p;
    p->next=NULL;

    //将剩余结点前端插入链表
    while(q!=NULL)
    {
        p=q;
        q=q->next;

        s=list->first;
        p->next=s->next;
        s->next=p;
    }
}

int findval_val(LinkList *list,ElemType key)//查找链表中首个值为key的元素位置
{
    int i=1;
    if(list->list_size==0)
    {
        return -1;
    }
    LNode *p=list->first->next;
    while(p!=NULL && p->data!=key)
    {
        p=p->next;
        i++;
    }
    if(p==NULL)
        return -1;
    else
        return i;
}
void clearLinkList(LinkList *list)//清空单链表
{
    if(list->list_size==0)
        return;
    LNode *p=list->first->next;
    while(p!=NULL)
    {
        list->first->next=p->next;
        free(p);
        p=list->first->next;
    }

    list->last=list->first;
    list->list_size=0;

}
void destroyLinkList(LinkList *list)//销毁单链表
{
    clearLinkList(list);
    free(list->first);
    list->first=list->last=NULL;
    list->list_size=0;
}

还有两个附加题
**(1)**拆分l1,l1存奇数位置元素,l2存偶数位置元素
**(2)**将有序的l1、l2合并为l3后仍有序
可以在前文基础上增加,或者像这样再来一个项目,尝试再建一个项目时,某些前文的type也是需要的,必要的:初始化函数void InitLinkList(LinkList *list);还有插入,排序和显示。
main.cpp

#include <iostream>
#include "SList.h"
using namespace std;

int main()
{
    ElemType item;
    LinkList L1,L2;
    InitLinkList(&L1);
    InitLinkList(&L2);
    printf("输入L1元素,以-1为结束标志:\n");
    while(scanf("%d",&item),item!=-1)
    {
        push_back(&L1,item);
    }
    printf("输入L2元素,以-1为结束标志:\n");
    while(scanf("%d",&item),item!=-1)
    {
        push_back(&L2,item);
    }
    //Depatch(&L1,&L2);
    //showList(&L1);
    //showList(&L2);
    LinkList L3;
    InitLinkList(&L3);
    Depatch(&L1,&L2);
    printf("拆分后链表:");
    showList(&L1);
    showList(&L2);
    mergerL(&L1,&L2,&L3);
    printf("合并后链表:");showList(&L3);

    return 0;
}


SList.h

#ifndef SLIST_H_INCLUDED
#define SLIST_H_INCLUDED
#include <stdio.h>
#include <assert.h>
#include <malloc.h>

typedef int ElemType;  //定义类型

typedef struct LNode  //定义结点
{
    ElemType data;   //数据域
    struct LNode *next;  //指向后继结点的指针域
}LNode,*PNode;  //PNode为节点类型指针

typedef struct LinkList  //定义链表
{
    PNode first;  //头指针
    PNode last;  //尾指针
    int list_size;  //链表中有效元素个数
}LinkList;
void InitLinkList(LinkList *list);//初始化链表
void showList(LinkList *list);//显示链表元素
void sortLinkList(LinkList *list); //排序
void push_back(LinkList *list,ElemType x);//向链表中尾插结点
/单链表的拆分//
void Depatch(LinkList *l1,LinkList *l2);//拆分l1,l1存奇数位置元素,l2存偶数位置元素
/单链表的合并//
void mergerL(LinkList *l1,LinkList *l2,LinkList *l3);//将有序的l1、l2合并为l3后仍有序
#endif // SLIST_H_INCLUDED

SLink.cpp

#include "SList.h"

void InitLinkList(LinkList *list) //初始化链表
{
    LNode *head=(LNode *)malloc(sizeof(LNode));//定义头节点
    assert(head!=NULL);  //断言空间是否分配成功
    head->next=NULL;  //将头节点指针域设置为空
    list->first=list->last=head;  //初始化链表中的头指针、尾指针
    list->list_size=0;//初始化链表的长度
}
LNode *_buyNode(ElemType x)//新增结点,注意:返回的是新增节点的指针
{
    LNode *s;
    s=(LNode *)malloc(sizeof(LNode));
    assert(s!=NULL);
    s->data=x;
    s->next=NULL;
    return s;
}
void push_back(LinkList *list,ElemType x) //向链表中尾插结点
{
    LNode *s;
    s=_buyNode(x);
    list->last->next=s;
    list->last=s;
    list->list_size++;
}

void showList(LinkList *list) //显示链表元素
{
    LNode *p;
    p=list->first->next;
    while(p!=NULL)
    {
        printf("%d->",p->data);
        p=p->next;
    }
    printf("Nul.\n");
}
void sortLinkList(LinkList *list) //排序
{
   if(list->list_size==0)
    return;
   LNode *p,*q,*s;
   //首元素结点之后断开
   p=list->first->next;
   q=p->next;//q记录断开后的节点地址
   p->next=NULL;
   list->last=p;//重新定为尾指针
   while(q!=NULL)  //依次扫描剩余结点
   {
       p=q;
       q=q->next;//重新定位p、q的位置,p指向剩余结点中每轮要插入的结点。q执行p的下一个节点

       s=list->first;//s指向待排序链表的头节点
       while(s->next!=NULL && s->next->data<p->data)
       {
           //如果s所指的下一个结点小于要插入的p所指结点,则s向后移动

           s=s->next;
       }
       //跳出循环后,s所指的下一个结点值大于p所指节点,则将p插在s之后

       if(s->next==NULL)//注意:如果插入的位置为最后一个节点,则修改尾指针位置
       {
           list->last=p;
       }
       //将p插在s之后
       p->next=s->next;
       s->next=p;
   }

}
/单链表的合并//
void mergerL(LinkList *L1,LinkList *L2,LinkList *L3) //将有序的l1、l2合并为l3后仍有序
{
    sortLinkList(L1);
    sortLinkList(L2);
    LNode *La,*Lb,*Lc;
    La=L1->first->next;
    Lb=L2->first->next;
    Lc=L3->first;
    while(La!=NULL && Lb!=NULL)
    {
        if(La->data<Lb->data)
        {
            Lc->next=La;
            Lc=Lc->next;
            La=La->next;
        }
        else
        {
            Lc->next=Lb;
            Lc=Lc->next;
            Lb=Lb->next;
        }
    }
    if(La!=NULL)
    {
        Lc->next=La;
        L3->last=L1->last;
    }
    if(Lb!=NULL)
    {
        Lc->next=Lb;
        L3->last=L2->last;
    }
    L3->list_size=L1->list_size+L2->list_size;
}
void Depatch(LinkList *L1,LinkList *L2)//拆分l1,l1存奇数位置元素,l2存偶数位置元素
{
    LNode *p,*q,*s;
    p=L1->first->next;
    L1->last=p;
    while(p!=NULL)
    {
        q=p->next;
        s=q->next;

        //将奇数位结点后端插入l1
        p->next=NULL;
        L1->last->next=p;
        L1->last=p;


        //将偶数位结点前端插入l2
        q->next=L2->first->next;
        L2->first->next=q;
        L2->last=q;

        p=s;//重新定位p

    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值