链表的基本操作
2015-07-20 23:11
190 查看
有链表的创建,增加、删除节点,链表的逆序、排序和销毁等。
链表反转的思路:
取出原始链表的第一个节点A,然后将该节点作为新链表的头节点。
现在状态为
原始链表:B->C->D->E
新链表:A
然后同上,变为了下面的状态
原始链表:C->D->E
新链表: B->A
原始链表:D->E
新链表: C->B->A
原始链表:E
新链表: D->C->B->A
原始链表:
新链表: E->D->C->B->A
很显然,对原始链表遍历一次,就完成了这个工作,所以这个算法的复杂度为O(n)。
通过对上面状态的变化分析,只要我们知道原始链表和新链表的头节点,我们就可以从原始链表取出第一个节点,然后将节点插入到新链表的第一个位置,由于两个链表的头结点现在都已经变化,所以我们不能丢失新头节点的地址。所以,我们要设置两个变量分别记录两个链表的头结点。下面程序中的old_head和 new_head分别表示原始链表的头节点和新链表的头节点。
程序如下,实现了迭代方式和递归方式:
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct tag { int m_val; char m_buf[32]; struct tag* m_next; }NODE,*pNODE; void link_init_tail(pNODE* phead); void link_init_head(pNODE* phead); void link_show(pNODE phead); void link_destory(pNODE* phead); void link_init_sort(pNODE* pphead); void link_delete(pNODE* phead, int val); void link_reverse(pNODE* phead); int main(int argc, char* argv[]) { int val = 0; pNODE phead = NULL; link_init_tail(&phead); link_show(phead); //link_init_head(&phead); //link_init_sort(&phead); putchar(10); link_reverse(&phead); //link_destory(&phead); link_show(phead); printf("\n"); while(scanf("%d", &val) == 1) { link_delete(&phead, val); link_show(phead); printf("\n"); } system("pause"); return 0; } void link_init_tail(pNODE* phead) { int val ; pNODE pnew = NULL, ptail = NULL; while(scanf("%d",&val) == 1) { pnew = (pNODE)calloc(1,sizeof(NODE)); pnew->m_val = val; if(*phead == NULL) { *phead = pnew; ptail = pnew; }else { ptail->m_next = pnew; ptail = pnew; } } } void link_init_head(pNODE* phead) { int val ; pNODE pnew = NULL; while(scanf("%d",&val) == 1) { pnew = (pNODE)calloc(1,sizeof(NODE)); pnew->m_val = val; pnew->m_next = *phead; *phead = pnew; } } void link_init_sort(pNODE* phead) { int val; pNODE pnew, pcur, ppre; while (scanf("%d",&val) == 1) { pnew = (pNODE)calloc(1,sizeof(NODE)); pnew->m_val = val; pcur = *phead; ppre = NULL; while(pcur&&pcur->m_val < pnew->m_val) { ppre = pcur; pcur = pcur->m_next; } if(ppre == NULL) { pnew->m_next = *phead; *phead = pnew; }else { pnew->m_next = pcur; ppre->m_next = pnew; } } } void link_show(pNODE phead) { pNODE pcur; pcur = phead; while(pcur != NULL) { printf("%3d",pcur->m_val); pcur = pcur->m_next; } } void link_destory(pNODE* phead) { pNODE pcur, ptmp = NULL; pcur = *phead; while(pcur) { ptmp = pcur ; pcur = pcur->m_next; free(ptmp); } *phead = NULL; } void link_delete(pNODE* phead, int val) { pNODE ppre, pcur; pcur = *phead; ppre = NULL; while(pcur && pcur->m_val != val) { ppre = pcur; pcur = pcur->m_next; } if(pcur == NULL) { printf("Not exist"); }else { if(ppre == NULL) { *phead = pcur->m_next; free(pcur); }else { ppre->m_next = pcur->m_next; free(pcur); } } } void link_reverse(pNODE* phead) { pNODE old_head = NULL; pNODE new_head = NULL; pNODE cur = *phead; while(cur != NULL) { old_head = cur->m_next; cur->m_next = new_head; new_head = cur; cur = old_head; } *phead = new_head; printf("After reverse:\n"); //link_show(*phead); }
链表反转的思路:
取出原始链表的第一个节点A,然后将该节点作为新链表的头节点。
现在状态为
原始链表:B->C->D->E
新链表:A
然后同上,变为了下面的状态
原始链表:C->D->E
新链表: B->A
原始链表:D->E
新链表: C->B->A
原始链表:E
新链表: D->C->B->A
原始链表:
新链表: E->D->C->B->A
很显然,对原始链表遍历一次,就完成了这个工作,所以这个算法的复杂度为O(n)。
通过对上面状态的变化分析,只要我们知道原始链表和新链表的头节点,我们就可以从原始链表取出第一个节点,然后将节点插入到新链表的第一个位置,由于两个链表的头结点现在都已经变化,所以我们不能丢失新头节点的地址。所以,我们要设置两个变量分别记录两个链表的头结点。下面程序中的old_head和 new_head分别表示原始链表的头节点和新链表的头节点。
程序如下,实现了迭代方式和递归方式:
#include <stdio.h> #include <malloc.h> typedef struct Node{ int data; struct Node* next; }Node; #define LIST_LEN 10 //链表长度 Node * List = NULL; //链表 //迭代方式 void reverse_ite(Node * list){ Node * old_head = NULL; //原来链表的头 Node * new_head = NULL; //新链表的头 Node * cur = list; //获得原来链表的头 //每次将原来链表的头取出,并插入到新链表中,并且是新链表的头 while(cur != NULL){ old_head = cur->next; //将原来链表的头取出,并将第二个节点作为头节点 cur->next = new_head; //将取出的头设为新链表的头 new_head = cur; //新链表的头就是目前新链表的头 cur = old_head; //接着处理 } List = new_head; } //递归方式 void reverse_recursive(Node * old_head, Node * new_head){ if(old_head == NULL){ List = new_head; return; } Node * tmp = old_head->next; //将原来链表的头取出,并将第二个节点作为原来链表的头节点用于下一层递归 old_head->next = new_head; //将取出的头设为新链表的头 reverse_recursive(tmp, old_head); //接着处理 }
相关文章推荐
- POJ 3620 Avoid The Lakes
- Activity初步认识
- [BZOJ1010][HNOI2008]玩具装箱toy
- Node.js(五)- 迅速node api
- onTouch事件机制
- 鉴于Eclipse下在线安装Pydev插件所遇见的问题,及其替代的离线安装的方法
- python类型比较的3种方式
- 直接插入排序
- QWidget属性,函数的学习
- [BZOJ1562][NOI2009]变换序列
- 进程内存
- 上海麻辣马资深程序员叶劲峰:我的游戏人生
- S3C2440时钟和电源管理
- Python filter()函数的用法
- CMSIS的简介
- AUTOMAKE 教程,
- Android中利用java反射机制Reflect
- 第一百零九天 how can I 坚持
- 数据库查询优化(转载)
- LINUX使用DVD光盘或者ISO作为本地YUM源