#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#if 1
typedef struct NODE
{
int data;
struct NODE *next;
}node;
#if 0
node *createlist_tail(void)
{
node * head = (node*)malloc(sizeof(node));
head = NULL;
node *p;
int data;
while (1){
node *s = (node*)malloc(sizeof(node));
printf("please input int data:");
scanf("%d", &data);
if(data == 0) break;
s->data = data;
printf("data=%d\n", s->data);
if(head == NULL){
head = s;//第一个节点来时,让头指针指向新节点
}
else{
p->next = s;//之后的节点来时,让P->next指针指向新节点
}
p = s;
}
if(head != NULL){
//因为有了新节点,所以head指针就不是指向NULL了
p->next = NULL;//尾插法P->next永远在尾巴上,最后之向NULL
}
return head;
}
#endif
node *createlist_tail(void)
{
node *head = (node*)malloc(sizeof(node));
node *p = head;//必须有,不然会崩,这里指向head,后面对p的操作等同于操作head
head->next = NULL;//加或不加不影响
// head = NULL;//这句一定不能加
int data;
while (1)
{
node *s = (node*)malloc(sizeof(node));
printf("please input data:");
scanf("%d", &data);
if(data == 0) break;
s->data = data;
printf("data=%d\n", s->data);
p->next = s;
p = s;
}
head = head->next;//不加遍历就会把头结点算进去
p->next = NULL;//尾插的最后指向NULL
return head;
}
node *createlist_head(void)
{
node *head = (node*)malloc(sizeof(node));
head->next = NULL;//头插的这一句话至关重要
// head->data = 0;
int data;
while (1)
{
printf("please input data:");
scanf("%d", &data);
if(data == 0) break;
printf("data=%d\n", data);
node *s = (node*)malloc(sizeof(node));
s->data = data;
/*最开始head->next是指向NULL的,因为是头插,所以第一个来的节点就是尾巴,这里让第一个节点保存head->next
就相当于让第一个节点的next指向NULL,后面再来的节点就不会指向NULL了*/
s->next = head->next;
head->next = s;//让头结点更改方向指向新节点,这里为什么不能是head->next=s->next还没想通
// s = s->next;//加不加无所谓
}
head = head->next;//不加的话,遍历会把头结点算进去
return head;
}
void print(node *head)
{
while (head != NULL)
{
printf("output=%d\n", head->data);
head = head->next;
}
}
void print_t(node *head)
{
node *p = head->next;
printf(":%d\n", head->data);
while (p != NULL)
{
printf("=%d\n", p->data);
p = p->next;
}
// printf("=%d\n", head->data);
// while (head->next != NULL)
// {
// printf("out=%d\n", head->data);
// head = head->next;
// }
}
int getlenlist(node *head)
{
int len = 0;
while (head != NULL)
{
head = head->next;
len++;
}
return len;
}
#if 0
node *reverselist(node *head)
{
if(head == NULL) return NULL;
node *ptr_pre = head;
node *ptr_cur = head->next;
if(ptr_cur == NULL) return head;
node *ptr_next = ptr_cur->next;
ptr_pre->next = NULL;
while (ptr_next != NULL){
ptr_cur->next = ptr_pre;
ptr_pre = ptr_cur;
ptr_cur = ptr_next;
ptr_next = ptr_next->next;
}
ptr_cur->next = ptr_pre;
return ptr_cur;
}
#endif
node *reverselist(node *head)
{
if(head == NULL || head->next == NULL) return head;
/*这一步包含了很多信息,reverselist函数返回的是一个指针,指针指向了头结点*/
node *p = reverselist(head->next);
/*明白了上面那一步,这一步就好理解了,将尾结点的next指针指向尾结点的前一个结点*/
head->next->next = head;
/*将尾结点的前一个结点的next指针指向NULL*/
head->next = NULL;
/*开始递归,直到链表的头结点变成尾结点结束*/
return p;
}
#endif
int main(int argc, char const *argv[])
{
#if 1
node * p = createlist_tail();
// node *p = createlist_head();
print(p);
int len = getlenlist(p);
printf("len=%d\n", len);
p = reverselist(p);//递归方法需要用指针接收
print_t(p);
len = getlenlist(p);
printf("len=%d\n", len);
#endif
return 0;
}
头插与尾插的区别已经做了注释,反转有循环与递归,递归的写法简洁了很多。