c/c++ 线性表之单向循环链表
c/c++ 线性表之单向循环链表
线性表之单向循环链表
不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点不是NULL,而是头节点。因为头尾相连,所以叫单向循环链表。
真实的第一个节点是头节点,头节点不存放数据,单纯为了编写程序方便。但是下面注释里写的【第一个节点】的含义是头节点的下一节点,也就是真实存放数据的第一个节点。
下面的代码实现了以下功能
| 函数 | 功能描述 |
|---|---|
| push_back | 从链表的最后插入节点 |
| push_front | 从链表的起始插入节点 |
| show_list | 打印出链表里每个节点的值 |
| pop_back | 删除链表最后一个节点 |
| pop_front | 删除链表起始节点 |
| insert_val | 在合适的位置插入一个节点; 比如原来的链表:1->3->NULL,当要插入的节点的值为2的时候,就会在1和3之间插入这个节点,插入后的链表:1->2->3->NULL |
| find | 查找指定的节点 |
| length | 返回链表中节点的个数 |
| delete_val | 删除指定的节点 |
| sort | 排序,重新排列节点 |
| resver | 按倒序,重新排列节点 |
| clear | 释放除了头节点之外的所有节点所占用的内存空间 |
| destroy | 释放所有节点的所占用的内存空间,包括头节点 |
whilenode.h
#ifndef __SEQNODE__
#define __SEQNODE__
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <memory.h>
#include <stdbool.h>
#define ElemType int
typedef struct Node{
ElemType data;
struct Node* next;
}Node;
typedef struct NodeList{
Node* first;
Node* last;
size_t size;
}NodeList;
void init(NodeList*);
void push_back(NodeList*, ElemType);
void push_front(NodeList*, ElemType);
void pop_back(NodeList*);
void pop_front(NodeList*);
void show_list(NodeList*);
void insert_val(NodeList*, ElemType);
Node* find(NodeList*, ElemType);
void delete_val(NodeList*, ElemType);
void sort(NodeList*);
void sort1(NodeList*);
void resver(NodeList*);
void resver1(NodeList*);
void resver2(NodeList*);
void clear(NodeList*);
void destroy(NodeList*);
#endif
whilenode.c
#include "seqnode.h"
void init(NodeList* list){
list->first = (Node*)malloc(sizeof(Node));
list->last = list->first;
list->last->next = NULL;
list->size = 0;
}
Node* create_node(ElemType val){
Node* node = (Node*)malloc(sizeof(Node));
assert(NULL != node);
node->data = val;
node->next = NULL;
return node;
}
void push_back(NodeList* list, ElemType val){
Node* p = create_node(val);
list->last->next = p;
list->last = p;
list->last->next = list->first;
list->size++;
}
void push_front(NodeList* list, ElemType val){
Node* p = create_node(val);
p->next = list->first->next;
list->first->next = p;
if(list->size == 0){
list->last = p;
list->last->next = list->first;
}
list->size++;
}
void show_list(NodeList* list){
Node* tmp = list->first->next;
while(tmp != list->first){
printf("%d->", tmp->data);
tmp = tmp->next;
}
printf("NULL\n");
}
void pop_back(NodeList* list){
if(list->size == 0)return;
Node* p = list->first;
while(p->next != list->last){
p = p->next;
}
p->next = list->first;
free(list->last);
list->last = p;
list->size--;
}
void pop_front(NodeList* list){
if(list->size == 0)return;
Node* p = list->first->next;
list->first->next = p->next;
if(list->size == 1){
list->last = list->first;
}
list->size--;
free(p);
}
void insert_val(NodeList* list, ElemType val){
if(list->size == 0){
push_back(list, val);
return;
}
Node* p = create_node(val);
Node* t = list->first;
while(t->next != list->first && val > t->next->data){
t = t->next;
}
if(t->next == list->first){
list->last = p;
}
p->next = t->next;
t->next = p;
list->size++;
}
//寻找目标节点
Node* find(NodeList* list, ElemType val){
if(0 == list->size){
return NULL;
}
Node* p = list->first->next;
do{
if(val == p->data){
return p;
}
p = p->next;
}
while(list->first != p);
return NULL;
}
//寻找目标节点的前一个节点
Node* find1(NodeList* list, ElemType val){
if(0 == list->size){
return NULL;
}
Node* p = list->first;
do{
if(p->next->data == val){
return p;
}
p = p->next;
}while(list->first != p);
return NULL;
}
void delete_val(NodeList* list, ElemType val){
if(0 == list->size)return;
Node* p = find1(list, val);
if(NULL == p)return;
if(p->next == list->last){
list->last = p;
}
Node* tmp = p->next;
p->next = p->next->next;
free(tmp);
list->size--;
}
void sort(NodeList* list){
if(list->size == 0 || list->size == 1)return;
Node* p = list->first->next;
Node* t = list->last = list->first;
list->last->next = list->first;
size_t s = list->size;
while(s-- > 0){
while(p->data > t->next->data && t->next != list->first){
t = t->next;
}
if(t->next == list->first){
list->last = p;
}
Node* tmp = p->next;
p->next = t->next;
t->next = p;
p = tmp;
t = list->first;
}
list->last->next = list->first;
}
void resver(NodeList* list){
if(list->size == 0 || list->size == 1)return;
Node* head = list->first->next;
Node* end = head;
list->last = list->first;
list->last->next = list->first;
while(head != list->first){
Node* tmp = head->next;
head->next = list->first->next;
list->first->next = head;
head = tmp;
}
list->last = end;
}
void clear(NodeList* list){
if(list->size == 0) return;
Node* b = list->first->next;
Node* q;
while(b != list->first){
q = b->next;
free(b);
b = q;
}
list->last = list->first;
list->last->next = list->first;
list->size = 0;
}
void destroy(NodeList* list){
Node* b = list->first;
Node* q;
while(b != list->first){
q = b->next;
free(b);
b = q;
}
}
whilenodemain.c
#include "seqnode.h"
int main(){
NodeList list;
init(&list);
int select = 1;
ElemType item;
Node* node = NULL;
while(select){
printf("*****************************************\n");
printf("*** [1] push_back [2] push_front ***\n");
printf("*** [3] show_list [4] pop_back ***\n");
printf("*** [5] pop_front [6] insert_val ***\n");
printf("*** [7] find [8] length ***\n");
printf("*** [9] delete_val [10] sort ***\n");
printf("*** [11] sort [12] resver ***\n");
printf("*** [13] [14] clear ***\n");
printf("*** [0] quit [15*]destroy ***\n");
printf("*****************************************\n");
printf("请选择:>");
scanf("%d", &select);
if(0 == select)
break;
switch(select){
case 1:
printf("请输入要插入的数据,以-1结束>\n");
while(scanf("%d",&item) && item != -1){
push_back(&list, item);
}
show_list(&list);
break;
case 2:
printf("请输入要插入的数据,以-1结束>\n");
while(scanf("%d", &item) && item != -1){
push_front(&list, item);
}
show_list(&list);
break;
case 3:
show_list(&list);
break;
case 4:
pop_back(&list);
show_list(&list);
break;
case 5:
pop_front(&list);
show_list(&list);
break;
case 6:
printf("请输入要插入的数据>\n");
scanf("%d",&item);
insert_val(&list, item);
show_list(&list);
break;
case 7:
printf("please enter what you shoule find out>\n");
scanf("%d",&item);
node = find(&list, item);
if(node == NULL){
printf("can not find %d\n", item);
}
break;
case 8:
printf("length is %ld\n", list.size);
break;
case 9:
printf("please enter what you want to delete>\n");
scanf("%d",&item);
delete_val(&list, item);
show_list(&list);
break;
case 10:
// sort(&list);
//show_list(&list);
break;
case 11:
sort(&list);
show_list(&list);
break;
case 12:
resver(&list);
show_list(&list);
break;
case 13:
resver(&list);
show_list(&list);
break;
case 14:
clear(&list);
show_list(&list);
break;
case 15:
destroy(&list);
break;
default:
break;
}
}
destroy(&list);
}
c/c++ 线性表之单向循环链表的更多相关文章
- 玩转C线性表和单向链表之Linux双向链表优化
前言: 这次介绍基本数据结构的线性表和链表,并用C语言进行编写:建议最开始学数据结构时,用C语言:像栈和队列都可以用这两种数据结构来实现. 一.线性表基本介绍 1 概念: 线性表也就是关系户中最简单的 ...
- c/c++ 线性表之双向循环链表
c/c++ 线性表之双向循环链表 线性表之双向循环链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,每个节点的before都指向前一个节点,最后一个节点的下一个节点不是NUL ...
- c/c++ 线性表之单向链表
c/c++ 线性表之单向链表 线性表之单向链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,最后一个节点的下一个节点是NULL. 真实的第一个节点是头节点,头节点不存放数据, ...
- 数据结构C语言实现系列——线性表(单向链表)
#include <stdio.h> #include <stdlib.h> #define NN 12 #define MM 20 typedef int elemType ...
- "《算法导论》之‘线性表’":双向循环链表
本文双链表介绍部分参考自博文数组.单链表和双链表介绍 以及 双向链表的C/C++/Java实现. 1 双链表介绍 双向链表(双链表)是链表的一种.和单链表一样,双链表也是由节点组成,它的每个数据结点中 ...
- 线性表->链式存储->循环链表
文字描述 循环链表是另一种形式的链式存储结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环.由此,从表中任一结点出发均可找到表中其他结点. 示意图 算法分析 插入.删除.查找等同单 ...
- 线性表List
数组array是基本的数据结构,但它的功能有限,线性表list可以认为是扩展了功能的数组.可以自动调整大小.添加和删除元素不需要其他元素移位. 根据指针数量和指向的不同,线性表分为单向链表.双向链表和 ...
- 线性表->链式存储->双向链表
文字描述 之前的链表(单链表.循环链表)的链式存储结构中只有一个指示直接后继的指针域.由此,从某个结点出发只能顺指针往后寻查其他结点.若要寻查结点的直接前驱,则需从表头指针出发.即单链表中,NextE ...
- 数据结构(java版)学习笔记(四)——线性表之循环链表
单向循环链表 PS:有阴影的结点是头结点 概念: 最后一个结点的链域值不为NULL,而是指向头结点 特点: 从表中的任意结点出发,都可以找到表中其他结点 循环条件 p==h 双向链表 概念 链表中的每 ...
随机推荐
- Perl输出复杂数据结构:Data::Dumper,Data::Dump,Data::Printer
输出复杂结构 Data::Dumper.Data::Dump.Data::Printer都可以用来输出复杂的数据结构.本文只介绍简单的几个输出形式,以后再需要的地方再详细介绍. 前两者建议传递数据结构 ...
- Go基础系列:函数(2)——回调函数和闭包
回调函数和闭包 当函数具备以下两种特性的时候,就可以称之为高阶函数(high order functions): 函数可以作为另一个函数的参数(典型用法是回调函数) 函数可以返回另一个函数,即让另一个 ...
- ARM 汇编指令 DCD
简介 DCD:数据定义( Data Definition )伪指令 一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化. 语法格式: 标号 DCD(或 DCDU) 表达式 DCD(或 ...
- shell编程基础(四): shell脚本语法之函数及调试
一.Shell脚本中的函数 和C语言类似,Shell中也有函数的概念,但是函数定义中没有返回值也没有参数列表.例如: #! /bin/sh fun(){ echo "Function fun ...
- YARN集群的mapreduce测试(四)
将手机用户使用流量的数据进行分组,排序: 测试准备: 首先同步时间,然后master先开启hdfs集群,再开启yarn集群:用jps查看: master上: 先有NameNode.SecondaryN ...
- 南大算法设计与分析课程复习笔记(2)L2 - Asymptotics
一.几种比较复杂度的符号 数据结构有描述,相关严格数学定义也不想说了,就这么过了吧. 二.最大子数组的几种解决方法 从最复杂的暴力解法过渡到最简单的动态规划 解析和代码见这里:http://www.c ...
- WPF 故事版例子
Storyboard std = new Storyboard(); DoubleAnimation a = new DoubleAnimation(); a.From =0; a.To =400; ...
- eclipse使用svn
主干(trunk).分支(branch ).标记(tag) 用法示例 + 图解 以svn为例,git的master相当于trunk,dev分支相当于branches --------------- ...
- js 点击文本框,预览选择图片
点击文件选择框,选择图片文件,通过FileReader对象,读取图片文件中的内容,存放于result中,具体代码如下 <input type="file" onchange= ...
- 4.4 explain 之 possible_keys 、key、key_len
一.possible_keys 显示可能应用在这张表中的索引,一个或多个. 查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用. 二.key 实际使用的索引.如果为null,则没有 ...