首页 > 技术文章 > 单链表逆置

zpfbuaa 2015-11-23 18:36 原文

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

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

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

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

代码:

 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<<"存储分配错误!\n";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<<"无效的插入位置!\n";return 0;}//判断是否合理,如果表为空或者表太短则返回0
24         else//接下来就开始插入
25         {
26             LinkNode *newnode=new LinkNode;//建立一个新结点
27             if(!newNode){cerr<<"存储分配错误!\n";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<<"无效的删除位置!\n";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<<"存储分配错误!\n";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<<"存储分配错误!\n";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<<"存储分配错误!\n";exit(1);}
93         destptr=destptr->link;
94         destptr->data=srcptr->data;//节点数据的传送
95         srcptr=srcptr->link;//传送源链指针到下一结点
96     }
97     destptr->link=NULL;//目标链收尾
98 };
View Code

 

推荐阅读