链表及其实现
来源:互联网 发布:时时彩娱乐平台源码 编辑:程序博客网 时间:2024/06/07 02:54
前言
本文在完成过程中,得到许多朋友的帮助,在此谢谢诸位。本人欢乐无限,技术有限,如有任何问题,欢迎各位不吝赐教。
1 表ADT
N个对象A1,A2,…,AN组成的一个线性序列,称为线性表,简称表。其中Ai是表中的数据元素,N为表的大小。若N=0,则该表为空表。Ai称为Ai+1的前驱,反过来Ai+1为Ai的后继。
在线性表中,数据元素之间的关系是一对一的,也就是说,除第一个元素外,其它元素都只有一个前驱,除最后一个元素,其它元素只有一个后继。
从存储结构上来看,表通常有两种:顺序表和链表。在顺序表中,各个对象的位置是由数组下标决定。而在链表中,对象的位置则由对象里的指针决定。在这里先主要讨论链表的实现(以后有机会再把顺序表补上,嘿嘿)。
链表的主要操作有以下这些:
find(x, L):查找关键字x第一次出现表L中的位置。
insert(x, L, p):将关键字x插入到位置p的后面。
delete(x, L):从表L中删除关键字x。
findPrevious(x, L):查找x的前驱的位置。
retrieve(p):返回位置p上的关键字。
最后,给出链表的递归定义方式(摘自《算法》Robert Sedgewick):链表是一种递归的数据结构,它或者为空,或者是指向一个结点的引用(指针),该结点含有一个泛型的元素和一个指向另一个链表的引用(指针)。在下面的C语言的实现中没有用到这个递归定义,感兴趣的童鞋可以试着用递归实现链表。
2 单链表的实现
2.1 单链表的模型和表示
链表相对于顺序表,具有更好的动态性。下面主要讨论最简单的一种链表——单链表。
在单链表中,表的每一个对象除了含有关键字element外,还有一个指针next。对象中还可以含有其他的辅助数据,称作卫星数据。当我们要移动关键字时,卫星数据也必须要移动。如果对象中含有大量卫星数据,则通常移动指针而不是对象本身。简单起见,我们这里没有卫星数据。所以对象就可以用下面图中的结点表示:
从上面的图中可以看出,结点包含两个域:数据域element和指针域next。现在数据域里面只有关键字没有卫星数据。指针域next指向该结点的后继,注意的是最后一个结点的next为NULL(在图中用^表示)。有了以上模型,链表结点的声明如下:
typedef int ElementType;typedef struct Node *Position;struct Node{ ElementType element; Position next;};
下面是一个含有5个对象的链表。
在用C语言实现的链表中,结点是动态地分配存储的,即程序在需要时才开辟一个结点的存储单元。C语言标准库<stdlib.h>提供了malloc函数来从操作系统那里获得所需要的存储空间。当然如果你申请的空间不再需要,记得用free函数来回收,以免内存泄漏噢。
为了使删除操作能够更一般的进行(主要为了避免删除第一个节点这种特殊情况),我们在表的第一个节点前面添加了一个头结点。则上面的表可以表示成这样:
2.2 单链表的C程序实现
首先是List.h:
typedef int ElementType;#ifndef LIST_H#define LIST_Hstruct Node;typedef struct Node *Position;typedef struct Node *List;List makeEmpty( List L );int isEmpty( List L );int isLast( Position p, List L );Position find( ElementType x, List L );Position findPrevious( ElementType x, List L );void delete( ElementType x, List L );void insert( ElementType x, List L, Position p );void deleteList( List L );Position header( List L );Position first( List L );Position advance( Position p );ElementType retrieve( Position p );#endif
Fatal.h:
#include <stdio.h>#include <stdlib.h>#define Error( Str ) FatalError( Str )#define FatalError( Str ) fprintf( stderr, "%s\n", Str ), exit( 1 )
List.c:
#include <stdlib.h>#include "List.h"#include "Fatal.h"struct Node{ ElementType element; Position next;};List makeEmpty( List L ){ if( L != NULL ) deleteList( L ); else{ L = malloc( sizeof( struct Node ) ); if( L == NULL ) FatalError( "Out of memory!" ); L->next = NULL; } return L;}int isEmpty( List L ){ return L->next == NULL;}int isLast( Position p, List L ){ return p->next == NULL;}Position find( ElementType x, List L ){ Position p; p = L->next; while( p != NULL && p->element != x ) p = p->next; return p;}/* If X is not found, then Next field of returned value is NULL */Position findPrevious( ElementType x, List L ){ Position p; p = L; while( p->next != NULL && p->next->element != x ) p = p->next; return p;}/* Delete from a list *//* Cell pointed to by P->Next is wiped out *//* Assume that the position is legal *//* Assume use of a header node */void delete( ElementType x, List L ){ Position p, tmpCell; p = findPrevious( x, L ); if( !isLast( p, L ) ){ /* X is found; delete it */ tmpCell = p->next; p->next = tmpCell->next; /* Bypass deleted cell */ free( tmpCell ); }}void insert( ElementType x, List L, Position p ){ Position tmpCell; tmpCell = malloc( sizeof( struct Node ) ); if( tmpCell == NULL ) FatalError( "Out of space!!!" ); tmpCell->element = x; tmpCell->next = p->next; p->next = tmpCell;}void deleteList( List L ){ Position p, tmp; p = L->next; /* Header assumed */ L->next = NULL; while( p != NULL ){ tmp = p->next; free( p ); p = tmp; }}Position header( List L ){ return L;}Position first( List L ){ return L->next;}Position advance( Position p ){ return p->next;}ElementType retrieve( Position p ){ return p->element;}
main.c:
#include <stdio.h>#include "List.h"void printList( const List L ){ Position p = header( L ); if( isEmpty( L ) ) printf( "Empty list\n" ); else{ do{ p = advance( p ); printf( "%d ", retrieve( p ) ); } while( !isLast( p, L ) ); printf( "\n" ); }}int main(int argc, char *argv[]) { List L; Position p; L = makeEmpty( NULL ); p = header( L ); printList( L ); for(int i = 0; i < 5; i++ ){ insert( i, L, p ); printList( L ); p = advance( p ); } for(int i = 0; i < 5; i += 2 ) delete( i, L ); printf( "Finished deletions\n" ); printList( L ); return 0;}
- 链表及其实现
- 块状链表及其实现
- C 链表及其接口的实现
- 双循环链表的实现及其功能!!!
- 链表原理详解及其实现
- java实现链表及其相关操作
- 链表的代码实现及其讲解
- 广义表及其实现
- 符号表及其基本实现
- skiplist 跳表详解及其编程实现--跳跃链表
- 循环链表及其接口函数的C++实现
- 二叉树的二叉链表存储及其Java实现
- 二叉树的三叉链表存储及其Java实现
- C语言实现单向链表及其各种排序
- 单链表 、带头结点的单链表、循环链表 及其实现
- STL之双向链表及其迭代器简单实现
- 链表及其基本操作的JAVA实现。
- c语言实现链表及其基本操作
- 算法之路一USACO: YOUR RIDE IS HERE
- 序列化和反序列化
- LeetCode 15. 3Sum
- HDOJ 6012 Lotus and Horticulture
- C++ STL : for_each
- 链表及其实现
- 详细的KVO总结,包括基本改变,使用案例,注意点.看我就够了!
- 如何在mac上安装opencv与python
- 简单的dns主从服务器搭建实验
- QFileInfo的简单用法
- JAVA之多态
- getResourceAsStream用法小结
- C语言实验——计算A+B(顺序结构)(sdut oj)
- 005 - 微信小程序 仿美团分类菜单 swiper分类菜单