单链表的建立,实现和操作

来源:互联网 发布:华为it 编辑:程序博客网 时间:2024/05/29 15:09
文中引用了一个单链表就地逆序的算法,在下资质愚钝想了半天没想出来,感谢这位仁兄的分享点击打开链接
#include<cstdio>#include<algorithm>#include<stack>#include<iostream>#include<malloc.h>using namespace std;typedef struct LNode{    int data;    struct LNode *next;} LinkList;//注意,单链表头节点不保存数据void InitList(LinkList *&head)//初始化单链表{    head=(LinkList*)malloc(sizeof(LinkList));    head->next=NULL;}//下面是两种创建单链表的方法//其中头节点为head融合在创建中,因提前建立,所以下方不使用void CreateListA(LinkList *&head,int a[],int n)//尾插法,依次将元素放在前一个元素后方{    LinkList *r,*s;//建立两个指针    /*head=(LinkList*)malloc(sizeof(LinkList));//为头结点分配空间    head->next=NULL;*/    r=head;    for(int i=0; i<n; i++)    {        s=(LinkList*)malloc(sizeof(LinkList));        s->data=a[i];        r->next=s;        r=s;//是r不断更新为所插入的下一个元素,再次进入循环    }//通过for循环实现尾插法    r->next=NULL;}void CreateListB(LinkList *&head,int a[],int n)//头插法,逻辑顺序与物理顺序相反{    LinkList *s;    /*head=(LinkList*)malloc(sizeof(LinkList));//分配空间    head->next=NULL;*/    s=head;    for(int i=0; i<n; i++)    {        s=(LinkList*)malloc(sizeof(LinkList));        s->data=a[i];        s->next=head->next;        head->next=s;//元素在插入的过程中新元素排在旧元素后面,所以逻辑物理顺序相反    }}void DestroyList(LinkList *&head)//销毁单链表{    LinkList *pre=head,*p=head->next;//创建两个指针,来回使用    while(p!=NULL)    {        free(pre);        pre=p;        p=pre->next;    }//逐一释放空间    free(pre);//释放最后一个}bool ListEmpty(LinkList *&head)//判断是否为空表(是否只含有一个头节点,若是,则为空){    return (head->next==NULL);//如果为空,则返回值为1}int ListLength(LinkList *head)//计算单链表长度{    int n=0;    LinkList *p=head;    while(p->next!=NULL)    {        n++;        p=p->next;    }    return n;}void DisplayList(LinkList *head)//输出线性表各个元素{    LinkList *p=head->next;//由于头节点不保存数据,所以从下一个开始    while(p!=NULL)    {        cout<<p->data<<' ';        p=p->next;    }    cout<<endl;}bool GetElem(LinkList *head,int i,int &e)//求线性表指定位置i的某个元素,将值赋给e,此处先判断,如成功则赋值输出{    LinkList *p=head;    for(int j=0; j<i&&p!=NULL; j++)    {        p=p->next;    }    if(p==NULL)//判断循环中断的原因,若为p==NULL,则说明超出单链表范围        return false;    else    {        e=p->data;        return true;    }}int  LocateElem(LinkList *head,int e)//找出哪一个位置的元素与e值相等,若不存在,输出0{    LinkList *p=head->next;    int i;    for(i=1; p!=NULL&&p->data!=e; i++)    {        p=p->next;    }    if(p==NULL)//判断终止条件        return 0;//代表不存在,遍历完毕    else        return i;}/*下面是单链表的插入和删除操作,可以借用if判断来得出插入或删除值。   也可直接调用函数*/bool ListInsert(LinkList *&head,int i,int e)//插入元素在第i个位置插入元素e{    LinkList *p=head,*s;    for(int j=0; j<i-1&&p!=NULL; j++)    {        p=p->next;    }    if(p==NULL)        return false;    else    {        s=(LinkList*)malloc(sizeof(LinkList));        s->data=e;        s->next=p->next;        p->next=s;//画图吧,画图好理解        return true;    }}bool ListDelete(LinkList *&head,int i,int &e)//删除线性表第i个元素,将删除元素的值赋给e{    LinkList *p=head,*q;    for(int j=0; j<i-1&&p!=NULL; j++)    {        p=p->next;    }    if(p==NULL)        return false;    else    {        q=p->next;        if(q==NULL)//判断p下一个节点是否为空,若为空则不满足条件            return false;        e=q->data;//将要删除的元素赋给e        p->next=q->next;        free(q);        return true;    }}void nixv(LinkList *&head)//就地逆序{   LinkList *p,*r;//   p=head->next;   head->next=NULL;   while(p!=NULL)   {       r=p->next;       p->next=head->next;       head->next=p;       p=r;//此处关键,建议画图   }}//以下是函数调用测试int main(){    LinkList *head;//初定义    InitList(*&head);//头节点    cout<<ListEmpty(*&head)<<endl;    int n;    cout<<"请输入元素个数n"<<endl;    cin>>n;    int m;    int a[100];    for(int i=0; i<n; i++)    {        cin>>a[i];    }    CreateListA(*&head,a,n);//此处为尾插,头插用法与此相同    //个人认为可以用不断插入的方法,这样可以动态分配内存,不用提前开数组依次填入    DisplayList(*&head);//输出测试    cout<<"元素个数为"<<ListLength(head)<<endl;    int e,z;    cout<<"请输入z,e,代表在第z位置插入元素e"<<endl;    cin>>z>>e;    ListInsert(*&head,z,e);//插入测试    DisplayList(*&head);//输出测试    int qq;    cout<<"请输入qq,代表删除第几位置的元素"<<endl;    cin>>qq;    int zz;    ListDelete(*&head,qq,zz);    DisplayList(*&head);//输出测试    cout<<"删除的元素是"<<zz<<endl;    cout<<"逆序输出"<<endl;    nixv(*&head);    DisplayList(*&head);    return 0;}

0 0