《顺序表和单链表的区别及应用场景+单链表经典例题》
来源:互联网 发布:php手机投票系统源码 编辑:程序博客网 时间:2024/06/05 17:15
前言:
线性表可分为:顺序表与链表。其中,顺序表又可分为动态的和静态的两种,链表可分为单向链表、单向循环链表、双向链表、双向循环链表等。本篇文章主要讲解动态顺序表与单向链表的区别与应用场景以及关于链表的一些经典例题。
正文:
顺序表与单链表的区别:
- 顺序表可以实现下标的快速访问,单链表则不可以,单链表必须从头依次遍历查找。
- 顺序表在中间或者头部插入节点时必须依次挪动后面节点到下一个节点位置,然而单链表却不用,单链表插入、删除节点比较方便。
- 顺序表每次增容固定大小的空间有可能造成空间浪费,但不用每次插入时都动态开辟空间,单链表每次插入节点时都必须动态开辟空间、删除节点时必须释放掉动态开辟的空间。
- 由于计算机设计的多级缓存机制遵循局部性原理,所以连续访问顺序表时缓存命中率较高,而单链表本身存储比较分散,连续访问时缓存命中率较低还会造成缓存污染。
顺序表与单链表的应用场景:
- 顺序表:
- 尾插尾删较多使用顺序表。
- 单链表:
- 头部或者中间插入较多使用单链表。
单链表经典例题:
//1.从尾到头打印单链表//2.删除一个无头单链表的非尾节点//3.在无头单链表的一个节点前插入一个节点//4.单链表实现约瑟夫环//5.逆置 / 反转单链表//6.单链表排序(冒泡排序&快速排序)//7.合并两个有序链表, 合并后依然有序//8.查找单链表的中间节点,要求只能遍历一次链表//9.查找单链表的倒数第k个节点,要求只能遍历一次链表
基本函数:
#include<stdio.h>#include<assert.h>#include<stdlib.h>typedef int DataType;//节点中数据类型typedef struct ListNode//节点数据结构{ DataType data; struct ListNode *next;} ListNode;ListNode *Find(ListNode *plist,DataType x)//查找函数,返回查找到节点的地址{ ListNode *cur = plist; while (cur) { if ((cur->data) == x) { return cur; } cur = cur->next; } return cur;}ListNode *BuyNode(DataType x)//产生一个节点并把节点中的数据置数,返回节点地址{ ListNode *plist = (ListNode *)malloc(sizeof(ListNode)); if (plist != NULL) { plist->data = x; plist->next = NULL; return plist; } return NULL;}void PrintList(ListNode *plist)//打印单链表{ assert(plist != NULL); while (plist) { printf("%d->",plist->data); plist = plist->next; } printf("NULL\n");}void PushBuck(ListNode **pplist,DataType x)//在函数尾部插入节点{ ListNode *cur = NULL; assert(pplist); cur = *pplist; if (*pplist == NULL) { *pplist = BuyNode(x); return; } while ((cur->next) != NULL) { cur = cur->next; } cur->next = BuyNode(x);}
从尾到头打印单链表:
void PrintTailToHead(ListNode *plist)//从尾到头打印单链表(采用递归实现){ if (plist == NULL) return; PrintTailToHead(plist->next); printf("%d->", plist->data);}
测试贴图:
删除一个无头单链表的非尾节点:
void EraseNonTail(ListNode *pos)//删除一个无头单链表的非尾节点{ ListNode *tmp = NULL; assert(pos); assert(pos->next); pos->data = pos->next->data; tmp = pos->next; pos->next = pos->next->next; free(tmp); tmp = NULL;}
测试贴图:
在无头单链表的一个节点前插入一个节点:
void InsertBeforeNode(ListNode *pos,DataType x)//在无头单链表的一个节点前插入一个节点{ ListNode *tmp = NULL; DataType ret = 0; assert(pos); tmp = BuyNode(x); tmp->next = pos->next; pos->next = tmp; ret = pos->data; pos->data = tmp->data; tmp->data = ret;}
测试贴图:
单链表实现约瑟夫环:
ListNode *JosephRing(ListNode *plist,int k)//单链表实现约瑟夫环{ int count = 0; ListNode *tmp = 0; assert(plist); while (plist != plist->next) { count = k; while (--count) { plist = plist->next; } plist->data = plist->next->data; tmp = plist->next; plist->next = plist->next->next; free(tmp); tmp = NULL; } return plist;}
测试贴图:
逆置 / 反转单链表:
ListNode *Reverse(ListNode *plist)//逆置 / 反转单链表{ ListNode *phead = NULL; ListNode *tmp = NULL; if ((plist == NULL) || (plist->next == NULL)) return plist; else { while (plist) { tmp = plist; plist = plist->next; if (phead == NULL) { phead = tmp; tmp->next = NULL; } else { tmp->next = phead; phead = tmp; } } return phead; }}
结果贴图:
单链表排序:
ListNode *Bubblesort(ListNode *plist)//单链表排序(冒泡排序&快速排序){ if ((plist == NULL) || (plist->next == NULL)) { } else { ListNode *cur = NULL; ListNode *next = NULL; ListNode *tail = NULL; while (tail != plist->next) { cur = plist; next = plist->next; while (next != tail) { if (cur->data > next->data) { DataType tmp = next->data; next->data = cur->data; cur->data = tmp; } cur = next; next = next->next; } tail = cur; } cur = next = tail = NULL; } return plist;}
结果贴图:
合并两个有序链表:
ListNode *Merge(ListNode *plist1,ListNode *plist2)//合并两个有序链表, 合并后依然有序{ ListNode *tail = NULL; ListNode *tmp = NULL; ListNode *plist = NULL; if (plist1 == NULL) { return plist2; } if (plist2 == NULL) { return plist1; } while (plist1 && plist2) { if (plist1->data < plist2->data) { tmp = plist1; plist1 = plist1->next; } else { tmp = plist2; plist2 = plist2->next; } if (plist == NULL) { plist = tmp; tail =ist; } else { tail->next = tmp; tail = tmp; } } if (plist1 == NULL) { tail->next = plist2; } else { tail->next = plist1; } return plist;}
结果贴图:
查找单链表的中间节点:
ListNode *FindMidNode(ListNode *plist)//查找单链表的中间节点,要求只能遍历一次链表{ assert(plist); ListNode *fast = plist; ListNode *slow = plist; while (fast && fast->next) { fast = fast->next->next; slow = slow->next; } return slow;}
结果贴图:
查找单链表的倒数第k个节点:
ListNode *FindTailKNode(ListNode *plist,int k)//查找单链表的倒数第k个节点,要求只能遍历一次链表{ ListNode *fast = plist; ListNode *slow = plist; assert(plist); while (--k) { fast = fast->next; assert(fast); } while (fast->next != NULL) { fast = fast->next; slow = slow->next; } return slow;}
结果贴图:
阅读全文
0 0
- 《顺序表和单链表的区别及应用场景+单链表经典例题》
- Java的String和StringBuffer的区别及应用场景
- 悲观锁和乐观锁的区别及应用场景
- svn checkout和export的区别及应用场景
- 面试考察get和post的区别及应用场景
- 二分法-二分查找的应用及三个经典例题
- 顺序表和链表的优缺点及使用场景
- MogoDB和Redis应用场景的区别
- Java IO:BIO和NIO区别及各自应用场景
- GCD 和 NSOperation 区别及各自应用场景
- Android commit和commitAllowingStateLoss区别及应用场景
- Java IO:BIO和NIO区别及各自应用场景
- Java IO:BIO和NIO区别及各自应用场景
- String,StringBuffer与StringBuilder的区别及应用场景
- String,StringBuffer与StringBuilder的区别及应用场景
- NIo、Bio、aio、 的原理及区别与应用场景
- mybatis与hibernate的区别及各自应用场景
- NIo、Bio、aio、 的原理及区别与应用场景
- STM32的CAN波特率计算
- 在ABAP/4中声明表格控制
- Docker入门六部曲——基本引导
- 用Appium让Android功能自动化测试飞起来
- 如何给线程命名
- 《顺序表和单链表的区别及应用场景+单链表经典例题》
- 各种容器和服务器之间的区别和联系
- 给文件打补丁
- 支付宝APP支付-php后台签名以及验签
- SQL Injection
- 字符串数组最长公共前缀
- Python迭代器与生成器实例演示
- 织梦模板下载:环保设计公司织梦模板
- PHP —— 不用XMAPP 搭建开发环境