一、表的常见操作
对于一个链表,某个元素有其前驱和后继。对表的操作:find返回关键字首次出现的位置;insert和delete插入和删除某个元素;findkth返回某个位置上的元素;
二、表的简单数组实现
定义一个数组要初始化大小,要实现动态数组的形式,势必会浪费一定资源。由于数组的特性,会涉及后继元素的平移吗,find和findkth花费线性时间,然而insert和delete会花费最大O(n)的时间。综上所述,由于数组需要预先分配空间、插入需平移,所以一般不需要数组来实现表。
三、实现表的一种思路------链表
链表是表的一种形式,现在主要用链表来代表表了。链表由一系列不必在内存中相连的结构组成。每个结构均含有表元素和指向包含该元素后继元的结构的指针。称为next指针,最后一个单元的指针指向null,ANSI C 规定NULL为0。nullptr是空指针,区分二者。空表会有一个表头和指向null的指针;
1、链表的定义(阎淑敏),数据结构与算法里面的那个太复杂了,现在一般也不要typedef了。
1 typedef struct LNode{ 2 ElemType data; 3 struct LNode *next; 4 }LNode,*LinkList; 5 //最后那样,相当于typedef struct Node *LinkList; 指向表头
链表的结构就是一个元素值和一个指向下一个节点(不是下一个节点的元素)的指针组成。定义的时候,要定义出指向表头的指针linklist。
另一种写法:
typedef char DataType; //假设结点的数据域类型为字符 typedef struct node{ //结点类型定义 DataType data; //结点的数据域 struct node *next;//结点的指针域 }LNode; typedef LNode *LinkList;
LNode *p; LinkList head; 注意: ①LinkList和ListNode *是不同名字的同一个指针类型(命名的不同是为了概念上更明确) ②LinkList类型的指针变量head表示它是单链表的头指针 ③LNode *类型的指针变量p表示它是指向某一结点的指针
2、find()找到某个元素的前一个节点
1 lnode find(Element x,linklist p) 2 { 3 //node p=l->next; 4 while(p!=null && p->next->Element !=x) 5 { 6 p=p->next; 7 } 8 return p; 9 }
3、delete() 删除某个元素
1 void delete(element x,linklist p) 2 { 3 lnode tmpcell; 5 6 while(p!=null && p->next->element==x) 7 { 8 tmpcell=p->next; 9 p->next=tmpcell->next; 10 free(tmpcell); 11 } 12 }
4、insert()插入
1 void insert(element x,lnode *p) 2 { 3 lnode tmp=malloc(sizeof(struct lnode));
if(tmp==NULL)FatalError("out of space!"); 4 tmp->element=x; 5 tmp->next=p->next; 6 p->next=tmp; //注意插入的是lnode,不是x 7 }
上面是给定插入位置和元素的代码。如果是给定一个元素,在链表中所有的这个元素后面插入一个值怎么传参和写代码?弄懂这个插入的原理,也很简单是不是。也是传入哨兵元素,插入元素和表头。然后一个while(0判断,不就可以了吗?所以,搞懂链表的基本定义和插入原理,什么代码都可以写出来。