头指针链表(复杂不常用,理解原理就行)
2018-01-23 13:52
393 查看
链表结的结构和链表的各项操作模块函数点
#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 typedef int LinkData; typedef struct _node//链表的数据类型 { LinkData data;//链表的数据 struct _node *next;//指向链表下一个结点的指针 }Node; //链表的头插 int insert_head(Node**h, LinkData data)//(头指针的地址,链表要的数据) { if(h == NULL) return FALSE; //创建新结点 Node* node = (Node*)malloc(sizeof(Node)/sizeof(char));//node接受新结点的地址 if(node == NULL) return FALSE; node->data = data;//结点里的data接受传过来的data node->next = *h;//结点里的指针接受头指针里的地址(即原先链表里第一个结点的地址) //next指向原先第一结点 *h指头指针自身地址里放的内容(原第一节点地址) *h = node;//node里存着新结点的地址,赋值给头指针(即头指针指向新结点) return TRUE; } //尾插 int insert_last(Node**h, LinkData data) { if(h == NULL) return FALSE; //创建新结点 Node* node = (Node*)malloc(sizeof(Node)/sizeof(char));//node接受新结点的地址 if(node == NULL) return FALSE; //给结点赋值 node->data = data;//结点里的data接受传过来的data node->next = NULL;//尾插进去的结点做最后一个结点(其内指针指向NULL) //找最后一个结点 Node*tmp = *h;//指针tmp指向第一个结点 if(tmp == NULL)//当前链表是个空表 { *h = node;//让tmp指向新建的结点node } else { while(tmp->next)//遍历链表找最后一个结点(最后一个结点的next指针指向NULL) { tmp = tmp->next;//tmp当前指向的结点(第一结点)里的next指针, //指向紧跟着当前结点的下一个结点,将当前next里存 } //的地址赋值给tmp,tmp则指向下个结点,依次遍历链表 tmp->next = node;//找到最后一个结点后跳出循环,当下next=NULL, //将新建结点地址(node里存着)赋值给next; //即原先最后的结点里的next指向node(新结点) //新建结点就是现在的最后一个结点,实现尾插 } return TRUE; } //在第pos个结点插入数据。链表从1开始没有第0个结点 int insert_pos(Node**h, int pos, LinkData data) { if(h == NULL || pos < 1) return FALSE; //创建新的结点 Node* node = (Node*)malloc(sizeof(Node)/sizeof(char)); if(node == NULL) { return FALSE; } //给结点成员变量赋值 node->data = data; if(*h == NULL)//h为接受到的头指针的地址,*h为头指针指向的位置 { if(pos != 1)//空表情况下,只能插在第一个结点处 { //不在第一结点处时 printf("当前为空表,无法在第%d结点处插入数据\n", pos); free(node);//释放之前创建的结点空间 return FALSE; } node->next = NULL; *h = node;//头指针指向新创的结点做第一结点 } else//非空表时需要找到插入位置的前一个结点 { if(pos == 1)//插在开头 { node->next = *h;//*h为原先第一结点的地址,赋值给新结点的next,next指向原先的第一结点 *h = node;//头指针指向新创的结点做第一结点 }//如果不做上述判断,当pos为1时,for循环条件不成立,直接跳到最后赋值语句,新结点的next指向原先第二个结点,原第一结点指向新建结点,即pos=1时最终插在原第一结点后面,与原意相悖 else { int i; Node* tmp = *h;//新建结构体指针遍历链表 for(i = 0; i < pos-2; i++)//找到pos位置的前一个结点,i从0开始,如pos=4,找3位置,需从1走2步到3(pos-2 = 4-2 =2) { if(tmp == NULL)//如果pos过大,会造成越界 break; tmp = tmp->next;//tmp->next里存着下个结点的地址,依次遍历 } if(tmp == NULL) { printf("插入位置越界\n"); free(node);//释放新建的结点 return FALSE; } //找到pos位置前的结点位置后 node->next = tmp->next;//tmp指向pos位置前的结点将其next赋值给新建结点的next, //即node->next指向原先pos位置的结点 tmp->next = node;//pos位置前的结点内的next指向新建结点node } } return TRUE; } int delete_pos(Node**h, int pos) { if(h == NULL || *h == NULL || pos < 1) return FALSE; Node* tmp = *h; Node* p ; if(pos == 1) { *h = tmp->next; free(tmp); } else { int i; for(i = 0; i < pos-2; i++) { if(tmp->next == NULL)//pos过大,越界 break; tmp = tmp->next; }//tmp指向pos前的结构体 if(tmp->next == NULL) { printf("删除位置越界\n"); return FALSE; } p = tmp->next;//p指向pos位置(要删)的结构体 tmp->next = p->next;//p->next指向紧跟pos位置后的结点,让pos前的结点里的next指向p->next保存的地址 free(p);//释放(删除)pos位置的结点 } return TRUE; } //逆序 int reverse_list(Node**h) { if(h == NULL || *h == NULL || (*h)->next == NULL) return FALSE; Node* tmp; Node* ptr = *h;//ptr指向首结点 Node* cur = (*h)->next;//cur指向第二结点 while(cur) { tmp = cur->next;//tmp保存第三结点的地址(第二结点的next保存着第三结点的地址) cur->next = ptr;//将第一结点的地址赋值给第二结点的next,使其指向第一结点 ptr = cur;//cur保存着第二结点的地址,ptr也就指向第二节点 cur = tmp;//使cur指向第三结点 }//最后ptr指向最后一个结点,cur指向NULL (*h)->next = NULL;//逆序后原第一结点成最后结点,最后结点的next要指向NULL *h = ptr;//头指针指向新的第一结点(原最后结点); return TRUE; } //显示数据 void Display(Node*h)//(头指针存的内容(第一结点的地址)) { if(h == NULL) return;//空函数无返回值,不需返回FALSE int count = 0;//计数数据个数 while(h)//遍历链表 { if(count++ % 4 == 0)//4个数据一行 { printf("\n"); } printf("%8d", h->data); h = h->next;//指向下一个结点 } printf("\n"); }
主函数,举例操作
int main() { Node*head = NULL;//初始化头指针 //插入元素 int i; for(i = 0; i < 10; i++) { //insert_head(&head, i);//(头指针地址, 数据) 9019 insert_last(&head, i); } //insert_pos(&head, 3, 1000); //delete_pos(&head, 11); Display(head); reverse_list(&head); Display(head); return 0; }
相关文章推荐
- C语言的指针、链表的原理和各类操作
- 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序
- C语言的指针、链表的原理及学生管理系统
- C++深度理解复杂链表的构造复制
- 指针理解错误之构建链表操作
- 理解c和c++的复杂类型声明 (掺杂指针)
- 理解复杂的const和typedef和指针的关系
- 复杂链表的复制(结点包含随机指针)
- 单向链表末尾插入一个节点(指向指针的指针该怎样理解)
- 【C语言】指针、链表的原理和各类操作相关心得以及学生信息管理系统的改写报告
- 理解复杂的C/C++声明 const, typedef , 函数指针
- C语言复杂指针理解
- 链表指针新理解以及插入里链表节点新方法
- 指针、链表的原理和各类操作相关心得以及学生信息管理系统
- apue和unp的学习之旅02——理解常用协议的原理
- 理解c和c++的复杂类型声明 (掺杂指针)
- C语言的指针、链表的原理和各类操作以及学生信息管理系统改进报告
- 复制复杂(多指针)链表
- C语言的指针、链表的原理和各类操作
- 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序