先说下单向链表的反转:
声明函数原型为:
void reverseLinkedList(item * header);
这里,item为链表的元素类型,并假定其中包含了一个指向下一个元素的指针字段:
item * next;
和一些数据字段。
函数参数header是一个指向item类型数据的指针,顾名思义,这个item类型的数据就是要反转的单向链表的头元素(注意,这里假定了这个单向链表是有头元素,而且头元素的数据类型与链表元素的类型是一致的)。
下面再做一些假设:
程序声明了一个全局变量或者预编译的常量即:
const int NULL = 0;
或者,
#define NULL 0
因此可以用NULL来表示一个空指针。
于是我们规定,header指向的链表的最后一个元素的next值为NULL。
现在我们来实现函数:- void reverseLinkedList(item * header){
- item * newNext = NULL, curItem = header->next, oldNext = header->next->next;
- while (oldNext != NULL){
- curItem->next = newNext;
- newNext = curItem;
- curItem = oldNext;
- oldNext = oldNext->next;
- }
- header.next = curItem;
- }
复制代码 以上算法中,通过三个指针curItem, newNext, oldNext分别指向当前操作的元素、当前操作的元素在新链表中的next(也就是curItem在原链表中的前一个元素)和当前操作元素的在原链表中的next,这样既保证了将当前操作的元素的next指向了它的前一元素,又保证了当前操作元素在原链表中的next所指向的元素地址不会丢失。
算法中还要注意这三个指针初始值的设置、主循环方式和循环停止条件的选择,让函数体最精简,避免无谓的条件测试。另外记得在退出函数之前更新header->next指针的内容,使其指向更新后链表的首元素。
当然,如果你把函数原型声明为:
void reverseLinkedList(item * first);
即参数为链表的第一个元素,则相应把函数实现为以下即可:- void reverseLinkedList(item * first){
- item * newNext = NULL, curItem = first, oldNext = first->next;
- while (oldNext != NULL){
- curItem->next = newNext;
- newNext = curItem;
- curItem = oldNext;
- oldNext = oldNext->next;
- }
- first = curItem;
- }
复制代码 对于双向链表的反转,问题就变得简单了,实际上就是交换item中next和previous指针的内容,如果有头元素,更新头元素next指针,指向原链表的最后一个元素。这里就不写出实现过程了。希望可以帮到你。 |