先看一下题目:以单链表做存储结构,写一实现线性表的就地逆置算法
两种思路:
1、采用头插法新建单链表时,得到的单链表数据域所组成的序列刚好是输入序列的逆序,所以这里的单链表的就地逆置可以考虑头插法实现,即将数据域第一个结点后的结点取出,再将取出的结点插入到头结点之后,重复操作,直至原第一个结点到达最后(next指针为空)
2、设置标志位,在结点的数据域添加flag标志。逆置操作其实就是把第i个和第n-i个结点的数据域中data值互换,这里可以设置flag标志,来达到i和n-i互换的目的。
C++实现如下(注释部分代码为头插法就地逆置的实现):
#include <iostream>
using namespace std;
struct Node//用于思路1
{
int data;
Node *next;
};
struct Note//用于思路2
{
int data, flag=0;
Note *next;
};
class LinkList
{
public:
LinkList(int a[], int n);//初始化单链表
void Inversion();//单链表的逆置操作,蛮力法的思想
void Print();//输出单链表
void Swap(int &a, int &b);//交换值
private:
//Node *p, *q,*r,*first;
Note *p, *q, *r, *first;
};
LinkList::LinkList(int a[], int n)//尾插法建立单链表
{
//first = new Node;
first= new Note;
Note *s;
r = first;
for (int i = 0; i < n; i++)
{
//s = new Node;
s=new Note;
s->data = a[i]; r->next = s; r = s;
}
r->next = NULL;
}
void LinkList::Inversion()
{//以下为头插法的思想实现单链表就地逆置
/*
p=first->next; q = p->next;
while (p->next != NULL)
{
p->next = q->next; //将p指向的(原第一个结点)后一个结点取出
q->next = first->next;first->next=q;//头插法就地逆置单链表,将取出的结点插入到头结点(first)之后
q = p->next;//q所指的结点插入到头结点之后,指向p指针(原第一个结点)之后,进行下一次“头插”
}
*/
//以下为设置标志位,实现单链表的就地逆置
p = first->next;
while (p->flag != 1)//控制交换的趟数,p指针记录当前操作的结点
{
q = p;//q指针用来做交换操作
while (q->next != NULL && q->next->flag != 1)//每一趟的终止条件,其中q->next!=NULL用来控制第一趟(第一趟到尾指针,所有结点的flag值均为0
{
Swap(q->data, q->next->data);//交换相邻结点的数据域
q = q->next;//q指针后移
}
q->flag = 1;
//Print();
}
}
void LinkList::Print()//输出单链表
{
Note *k;
k = first->next;
while (k!= NULL)
{
cout << k->data << '\t';
k= k->next;
}
cout << endl;
}
void LinkList::Swap(int &a, int &b)//位运算交换值,引用参数,改变实参
{
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,10 };
LinkList T(a, 10);
T.Print();
T.Inversion();
T.Print();
return 0;
}