#include <iostream>
using namespace std;
typedef struct listnode
{
int date;
struct listnode *next;
}listnode;
void Init(listnode **head) //链表初始化
{
listnode *p=new listnode;
p->date=0;
p->next=NULL;
*head=p;
printf("初始化带头接点的链表\n");
}
void Insert(listnode **head,int date) //插入
{
if (!head)
{
return;
}
listnode *p=new listnode;
p->date=date;
p->next=NULL;
listnode *temp=*head;
while(temp->next)
{
temp=temp->next;
}
temp->next=p;
}
void print(listnode *head) //打印
{
listnode *temp=head;
while(temp->next)
{
cout<<temp->next->date<<" ";
temp=temp->next;
}
cout<<endl;
}
void Reserve(listnode *head) //链表逆序
{
listnode *p1,*p2,*p3;
if (head->next==NULL)
{
printf("链表为空\n");
return;
}
p1=head,p2=p1->next; //p1指向头结点 p2指向头结点下一个结点即第一结点
while(p2)
{
p3=p2->next; //p3刚开始是第一个结点的后继,如果null,则跳出循环
p2->next=p1; //改变结点的方向
p1=p2; //把p1移动到p2
p2=p3; //p2移动到p3
}
p2=new listnode; //循环跳出后p2指向null,要把p2重新指向一个空结点,作为新的头结点
p2->next=p1; //头节点的后继指向原始链表的最后一个结点
head->next->next=NULL;//原始链表的头结点后的第一个结点作为新的链表的末尾
head=p2; //头指针指向反转后的头结点
print(head); //打印出9 8 7 6 5 4 3 2 1 0
}
int main()
{
listnode *l;
Init(&l);//为什么要对l取地址?因为我们需要用二级指针
for (int i = 0; i < 10; ++i)
{
Insert(&l,i); //
}
print(l); //打印出0 1 2 4 5 6 7 8 9
Reserve(l);//链表逆序
print(l);//打印出 0
return 0;
}
//为什么我么要用二级指针?
//因为一级指针我们只能修改指针指向的内容,不能修改指针自身的值,当我们没有给一级指针分配内存时,直接传递指针到
//函数内,只是该指针的拷贝,函数操作完只能在本函数内实现功能如上面Reserve()函数里的print()可以打印出逆序的效果,但是
//main函数里调用完Reserve(),在调用print函数却打印不出逆序的效果,应为l并没有指向修改过的链表
详细点理解二级指针:
#include <iostream>
#include <string.h>
using namespace std;
void fun1(char* str)
{
str = new char[20];
strcpy (str, "test string");
}
void fun2(char** str)
{
*str = new char[20];
strcpy (*str, "test string");
}
int main()
{
char* s = NULL;
cout << "call function fun1" << endl;
fun1 (s);
if (!s)
cout << "s is null!" << endl;
else
cout << s << endl;
cout << "call function fun2" << endl;
fun2 (&s);
if (!s)
cout << "s is null!" << endl;
else
cout << s << endl;
return 0;
}
结果:
分析:
在fun1中,当调用str = new char[20]时,str和s已经没什么关系了,相当于在fun1中复制了一个指针,这个指针指向的空间存储了字符串“test string”,但s仍指针NULL。当调用fun2时,因为是二级指针,s指向str,这里*str = new char[20],*str就是s,所以给*str分配空间就是给s分配空间。这样解释应该就很清楚了。
画图为例:
fun1执行时
fun2执行时
如图所示,在fun1种str是s的拷贝,给str分配空间跟s没有关系,在fun2种str是二级指针,指向s,能够通过控制*str从而给s分配空间。