• 单链表逆置


    单链表在数据结构中算是一个十分基础的结构。在单链表上可以有很多的其他衍生比如,循环链表,带头结点的单链表,双向链表等等。同时单链表在实际应用中也很有很重要的意义。举例说明:集合的交集、并集问题,使用循环链表可以解决约瑟夫环问题、使用链表可以解决多项式的加法乘法。

    也许在以后的学习中很少自己再完整写过链表,但是在数据结构这门课的学习中,将一些基础的链表操作写一遍是很重要的。

    单链表的一些优点:相对于顺序表而言,插入删除算法较简便,但是对于查找以及返回某位置的数据却没有顺序表方便。

    下面代码给出单链表的结构定义,以及简单的逆序操作。

    代码:

     1 #include<bits/stdc++.h>
     2 
     3 #define max_size 1000010
     4 int a[max_size];
     5 
     6 using namespace std;
     7 
     8 typedef int DataType;//类型定义
     9 typedef struct node  //单链表
    10 {
    11     DataType data;
    12     struct node* next;
    13 } LinkedNode,*LinkList;
    14 
    15 /****由数组创建单链表****/
    16 LinkList CreateList(DataType a[],int n)
    17 {
    18     LinkedNode* ListHead=new LinkedNode();
    19     ListHead->data=a[0];
    20     ListHead->next=NULL;
    21     for(int i=n-1; i>=1; i--)
    22     {
    23         LinkedNode* p=new LinkedNode();
    24         p->data=a[i];
    25         p->next=ListHead->next;
    26         ListHead->next=p;
    27     }
    28     return ListHead;
    29 }
    30 
    31 void PrintList(LinkList ListHead)
    32 {
    33     if(NULL==ListHead)cout<<"The List is empty!"<<endl;
    34     else
    35     {
    36         LinkedNode* p=ListHead;
    37         while(p!=NULL)
    38         {
    39             cout<<p->data<<" ";
    40             p=p->next;
    41         }
    42         cout<<endl;
    43     }
    44 }
    45 
    46 void ReverseList(LinkedNode* pCur,LinkList& ListHead)//递归算法
    47 {
    48     if( (NULL==pCur)||(NULL==pCur->next) )
    49     {
    50         ListHead=pCur;
    51     }
    52     else
    53     {
    54         LinkedNode* pNext=pCur->next;
    55         ReverseList(pNext,ListHead); //递归逆置后继结点
    56         pNext->next=pCur;            //将后继结点指向当前结点。
    57         pCur->next=NULL;
    58     }
    59 }
    60 
    61 int main()
    62 {
    63 
    64     while(true)
    65     {
    66         int n;
    67         cout<<"请输入创建单链表的长度:"<<endl;
    68         cin>>n;
    69         for(int i=0; i<n; i++)
    70         {
    71             cout<<"请输入第"<<i+1<<"个数据:";
    72             cin>>a[i];
    73         }
    74         LinkedNode* list=CreateList(a,n);
    75         cout<<"逆置前:"<<endl;
    76         PrintList(list);
    77         LinkedNode*pTemp=list;
    78         ReverseList(pTemp,list);
    79         cout<<"逆置后:"<<endl;
    80         PrintList(list);
    81     }
    82     return 0;
    83 }

    下面给出其他操作的代码:

    单链表结构定义:

     1 //程序2-15(单链表的结构定义)
     2 
     3 typedef int DataType;
     4 typedef struct node//链表结点
     5 {
     6     DataType data;//数据域
     7     struct node *link;//链接指针域
     8 }LinkNode, *LinkList;
     9 
    10 //单链表适用于插入或删除频繁、存储空间需求不定的情形
    11 
    12 /*  (1)单链表中数据的逻辑结构与其物理结构可能不一致,
    13          通过指针将各个元素按照线性表的逻辑顺序连接起来
    14     (2)单链表的长度可以扩充
    15     (3)对单链表的便利和查找只能从头指针指示的首元节点开始,
    16          不能像顺序表那样直接访问某个指定的节点
    17     (4)当进行插入或删除运算时,只需修改相关结点的指针域即可,既方便又快捷
    18     (5)由于单链表的每个结点带有指针域,因而比顺序表需要的存储空间多
    19 */

    单链表的插入算法:

     1 //程序2-16(单链表插入算法)
     2 
     3 int Insert(LinkList& first,int i,DataType x)//将新元素x插入到第i个节点的位置。
     4                                             //i从1开始,i=1,表示插入到原首结点之前
     5 {
     6     if(!first||i==1)//插入到空表或非空表的首元结点
     7     {
     8         LinkNode *newnode=new LinkNode;//建立新的结点
     9         if(!newnode){cerr<<"存储分配错误!
    ";exit(1);}
    10         newnode->data=x;
    11         newnode->link=first;first=newnode;//新结点成为第一个结点
    12     }
    13     else//插入到链中或链尾
    14     {
    15         LinkNode *p=first;//为了找到第i-1个结点,需要新建一个指针来找到第i-1个结点
    16         int k=1;
    17         while(P!=NULL&&k<i-1)
    18         {
    19             p=p->link;
    20             k++;
    21         }//利用循环将p指向第i-1个结点的位置
    22         if(p==NULL&&first)
    23         {cerr<<"无效的插入位置!
    ";return 0;}//判断是否合理,如果表为空或者表太短则返回0
    24         else//接下来就开始插入
    25         {
    26             LinkNode *newnode=new LinkNode;//建立一个新结点
    27             if(!newNode){cerr<<"存储分配错误!
    ";exit(1);}
    28             newnode->data=x;
    29             newnode->link=p->link;
    30             p->link=newnode;
    31         }
    32     }
    33     return 1;
    34 };
    View Code

    单链表的删除算法:

     1 //程序2-17(单链表的删除算法)
     2 
     3 int Remove(LinkList &first,int i,DataType &x)//将单链表的第i个元素删去,i从1开始,
     4                                              //        引用型参数x返回被删元素的值
     5 {
     6     LinkNode *q,*p;//p来表示第i-1个结点的位置,q来表示要删除的结点
     7     int k;
     8     if(i<=1){q=first,first=first->link;}//删除首结点
     9     else//删除链表中部或尾部结点
    10     {
    11         p=first;
    12         k=1;
    13         while(p!=NULL&&k<i-1)//找到第i-1个节点的位置
    14         {
    15             p=p->link;
    16             k++;
    17         }
    18         if(p==NULL||p->link==NULL)//如果表太短或表为空 则返回0
    19         {cerr<<"无效的删除位置!
    ";return 0;}
    20         q=p->link;//保存第i个结点
    21         p->link=q->link;//将第i-1个结点和第i+1个结点链接
    22     }
    23     x=q->data;//取出被删结点的数据值
    24     delete q;//删除结点
    25     return 1
    26 }
    View Code

    单链表的一些其他操作(初始化、表空、清空、表长计算等):

     1 //程序2-18(单链表部分常用操作的实现)
     2 //带头结点的单链表
     3 void initList(LinkList &first)//初始化单链表
     4 {
     5     first=new LinkNode;
     6     if(!first){cerr<<"存储分配错误!
    ";exit(1);}
     7     first->link=NULL;
     8 };
     9 
    10 void clearList(LinkList &first)//清空单链表
    11 {
    12     LinkNode *q;//借用指针
    13     while(first->link!=NULL)//当链表不空时,删除所有的结点
    14     {
    15         q=first->link;
    16         first->link=q->link;//保存被删结点,从链表上摘下该结点
    17         delete q;//删除该结点
    18     }
    19 };
    20 
    21 int Length(LinkList &first)//计算表的长度(结点个数减一)
    22 {
    23     LinkNode *p=first->link;
    24     int count=0;
    25     while(p!=NULL)
    26     {
    27         p=p->link;
    28         count++;
    29     }
    30 };
    31 
    32 int isEmpty(LinkList &first)//判断单链表是否为空,为空则返回1;不空则返回0
    33 {
    34     return (first->link==NULL);
    35 }
    36 
    37 LinkLode* Search(LinkList &first,DataType x)//在单链表中查找第一个等于x的结点,查找成功则返回该结点的位置,否则返回NULL
    38 {
    39     LinkNode *p=first->link;
    40     while(p!=NULL&&p->data!=x)
    41     {
    42         p=p->link;
    43     }
    44     return p;
    45 };
    46 
    47 LinkNode *Locate(LinkList &first,int i)//在单链表对第i个结点定位,函数返回第i个结点的位置,否则返回NULL
    48 {
    49     if(i<0)return NULL;
    50     LinkNode *p=first;
    51     int k=0;
    52     while(P!=NULL&&k<i)
    53     {
    54         p=p->link;
    55         k++;
    56     }
    57     return p;
    58 };
    59 
    60 int Insert(LinkList &first,int i,DataType x)//将新的元素x插入到表中第i个位置,如果i不合理则函数返回0,否则返回1
    61 {
    62     LinkNode *p=Locate(first,i-1);//调用定位函数,将p指针指向单链表的第i个位置
    63     if(p==NULL)return 0;//如果i不合理,返回0
    64     LinkNode *s=new LinkNode;
    65     if(!s){cerr<<"存储分配错误!
    ";exit(1);}
    66     s->data=x;
    67     s->link=p->link;//将s链接到p之后
    68     p->link=s;//调整p的下一个结点,指向s
    69     return 1;//插入成功,函数返回1
    70 };
    71 
    72 int Remove(LinkList &first,int i,DataType &x)
    73 {
    74     LinkNode *p=Locate(first,i-1);//将p指向单链表的第i-1个位置
    75     if(P==NULL||p->link==NULL)return 0;//i不合理则函数返回0
    76     LinkNode *q=p->link;//用q来保存被删的结点
    77     p->link=q->link;//重新连接 将第i-1个结点和第i+1个结点链接
    78     x=q->data;//取出被删结点的数据
    79     delete q;//删除这个结点
    80     return 1;//删除成功则函数返回1
    81 };
    82 
    83 void Copy(LinkList &first1,LinkList &first2)
    84 //函数假定链表first1已存在且为空,即first1的头结点已创建且first1->link==NULL;
    85 //复制链表first2的全部结点到空链表first1中
    86 {
    87     LinkNode *srcptr=frist2->link;//srcptr是源指针
    88     LinkNode *destptr=first1;//destptr是目标链尾指针
    89     while(srcptr->link!=NULL)//利用while循环,将first2中的每个结点复制到first1中
    90     {
    91         destptr->link=new LinkNode;//新结点链接到目标链尾
    92         if(!destptr){cerr<<"存储分配错误!
    ";exit(1);}
    93         destptr=destptr->link;
    94         destptr->data=srcptr->data;//节点数据的传送
    95         srcptr=srcptr->link;//传送源链指针到下一结点
    96     }
    97     destptr->link=NULL;//目标链收尾
    98 };
    View Code
  • 相关阅读:
    Android Activity的事件分发机制-源码解析
    Android ViewGroup的事件分发机制-源码分析
    Android View的事件分发机制-源码解析
    Activity中的setContentView(R.layout.xxx)源码分析
    android 6.0动态权限的申请
    java 回行矩阵的打印
    Masonry解析ios屏幕适配
    CollectionsUtil 类
    Request.url请求路径的一些属性
    .net中HttpCookie使用
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/4989302.html
Copyright © 2020-2023  润新知