抛弃繁杂的定义,以实用,实战的角度来学习数据结构,这将使得数据结构的学习非常的简单。
前面已经学习了单链表的创建操作:http://blog.csdn.net/morixinguan/article/details/68951912
这节,将单链表温习的笔记共享出来,然后写一个例子,以防自己忘记。
1、单链表的数据结构的定义:
struct list *create_node(int data) ; 如何创建单链表的节点,主要分以下步骤: (1)给当前的每个节点的数据结构配置定量的空间大小 ep : struct list *node = malloc(sizeof(struct list)); (2)清节点数据(由于结构体变量在未初始化的时候,数据是脏的) ep : memset(node,0,sizeof(struct list)); (3)给节点初始化数据 ep : node->id = data ; (4)将该节点的指针域设置为NULL ep : node->next = NULL ;3、单链表的尾插:
尾插节点函数原型可定义如下:
header->next = new
尾插流程如下:
(1)获取当前节点的位置,也就是访问头节点 ep : struct list *p = header ; (2)判断是否为最后一个节点,如果不是,移动到下一个节点,如果是,将数据插入尾部。 ep : while(NULL != p->next) p = p->next ; p->next = new ;4、单链表的头插
所以可以推出头插流程如下:
(1)获取当前节点的位置,也就是访问头节点 ep : struct list *p = header ; (2)新的节点的下一个节点设置为原来头节点的下一个节点(第一个节点) ep : new->next = p->next ; (3)原来的头节点的下一个节点设置为现在新插入的头节点 ep : p->next = new ;5、单向链表的遍历
从图中可以得出信息,如果我们要打印出各个节点的数据,要考虑以下问题:
(1)需要打印头节点吗?(头节点肯定是不用打印的,因为这是我们为了操作方便而设置的一个节点)。 (2)这条链表有多少个节点我们怎么知道?(通过判断该链表是否已经到达了尾节点,标志就是NULL)那么可以得到流程如下:
(1)获取当前节点的位置,也就是访问头节点 ep : struct list *p = header ; (2)由于头节点我们不需要去打印它,这时候,初始化打印的节点需要从第一个节点开始。 ep : p = p->next ; (3)判断是否为最后一个节点,如果不是,先打印第一个节点的数据(1),然后移动到下一个节点(2),重复这两个步骤。 如果是最后一个节点,直接打印数据即可。 while(NULL != p->next){ printf("node:%d\n",p->data) ; p = p->next ;} printf("node:%d\n",p->data); 当然还可以一句代码解决,这样就达到了先偏移,后取数据。 while(NULL != p->next){ p = p->next ; printf("node:%d\n",p->data) ; }6、单向链表的删除
删除节点的函数原型可定义如下:
int detele_list_node(struct list *pH , int data);
单向链表的删除要考虑两种情况,一种的普通节点的删除(当然,头节点不能算)
还有一种是尾节点的前一个节点的删除情况,注意,删除完节点还需要释放对应节点的内存空间。
(1)先定义两个指针,一个表示当前的节点,另一个表示当前节点的上一个节点。 ep : struct list *p = header ; //当前节点 struct list *prev = NULL ; //当前节点的上一个节点 (2)遍历整个链表,同时保存当前节点的前一个节点 ep : while(NULL != p->next) { //保存了当前的节点的前一个节点 prev = p ; //保存当前偏移的节点 p = p->next ; return 0 ; } (3)在遍历的过程中查找要删除的数据 ep : while(NULL != p->next) { //保存了当前的节点的前一个节点 prev = p ; //保存当前偏移的节点 p = p->next ; //查找到了数据 if(p->id == data) { } return 0 ; } (4)查找到了数据后,分两种情况删除 ep : 普通节点的删除 if(p->id == data) { prev->next = p->next ; free(p); } ep : 考虑尾节点的下一个节点为NULL的节点删除 if(p->id == data) { if(p->next == NULL) { prev->next = NULL ; free(p); } }5、单向链表的逆序操作
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct slist { int id ; struct slist *next ; }L; //创建一个节点 L *create_node(int data) { //给每个节点分配结构体一样的空间大小 L *p = malloc(sizeof(L)); if(NULL == p) { printf("malloc error!\n"); return NULL ; } //由于结构体在未初始化的时候一样是脏数据,所以要清 memset(p,0,sizeof(L)); //初始化第一个节点 p->id = data ; //将节点的后继指针设置为NULL p->next = NULL ; } //链表的尾插 void tail_insert(L *pH , L *new) { //获取当前的位置 L *p = pH ; //如果当前位置的下一个节点不为空 while(NULL != p->next) { //移动到下一个节点 p = p->next ; } //如果跳出以上循环,所以已经到了NULL的这个位置 //此时直接把新插入的节点赋值给NULL这个位置 p->next = new ; } //链表的头插 void top_insert(L *pH , L *new) { L *p = pH ; new->next = p->next ; p->next = new ; } //链表的遍历 void Print_node(L *pH) { //获取当前的位置 L *p = pH ; //获取第一个节点的位置 p = p->next ; //如果当前位置的下一个节点不为空 while(NULL != p->next) { //(1)打印节点的数据 printf("id:%d\n",p->id); //(2)移动到下一个节点,如果条件仍为真,则重复(1),再(2) p = p->next ; } //如果当前位置的下一个节点为空,则打印数据 //说明只有一个节点 printf("id:%d\n",p->id); } //删除链表中的节点 int detele_list_node(L * pH , int data) { //获取当前头节点的位置 L *p = pH ; L *prev = NULL; while(NULL != p->next) { //保存当前节点的前一个节点的指针 prev = p ; //然后让当前的指针继续往后移动 p = p->next ; //判断,找到了要删除的数据 if(p->id == data) { //两种情况,一种是普通节点,还有一种是尾节点 if(p->next != NULL) //普通节点的情况 { prev->next = p->next ; free(p); } else //尾节点的情况 { prev->next = NULL ; //将这个尾节点的上一个节点的指针域指向空 free(p); } return 0 ; } } printf("没有要删除的节点\n"); return -1 ; } void trave_list(L * pH) { //保存第一个节点的位置 L *p = pH->next; L *pBack; int i = 0 ; if(p->next == NULL || p == NULL) return ; while(NULL != p->next) //遍历链表 { //保存第一个节点的下一个节点 pBack = p->next ; //找到第一个有效节点,其实就是头指针的下一个节点 if(p == pH->next) { //第一个有效节点就是最后一个节点,所以要指向NULL p->next = NULL ; } else { /* new->next = p->next ; p->next = new ; */ p->next = pH->next ; //尾部连接 } pH->next = p ; //头部连接 p = pBack ; //走下一个节点 } top_insert(pH,p); //插入最后一个节点 } int main(int argc , char **argv) { //创建第一个节点 int i ; L *header = create_node(0); for(i = 1 ; i < 10 ; i++) { tail_insert(header,create_node(i)); } Print_node(header); detele_list_node(header,5); putchar('\n'); Print_node(header); putchar('\n'); trave_list(header); Print_node(header); return 0 ; }运行结果: