线性表
定义:由零个或多个数据元素组成的有限序列
记为:L=(a1,a2…an)
a1,a2…ai-1为ai的前驱 ai-1为ai的直接前驱
ai+1,ai+2…an为ai的后继,ai+1为ai的直接后继
———— L->线性表的名称 n->线性表的长度 n=0->空表
线性表的基本操作
(1)initlist(L):初始化操作,建立一个空的线性表L
(2)listempty(L):若为空表返回True,否则返回False
(3)clearlist(L):将线性表清空
(4)getlen(L):返回线性表L的长度
(5)locate(L,x):返回x在L中第一次出现的位序,若没有则返回0
(6)getelem(L,i,e):返回L中第i个元素的值并赋值给e
(7)insert(L,i,x):在L的第I个位置上插入一个值为x的元素
(8)delete(L,i,e):删除L中第i个元素并赋值给e
(9)list(L):按先后顺序输出L的所有元素
顺序表
定义:用一段地址连续的存储单元依次存储线性表的数据元素
顺序表的类型定义
typedef int elemtype;/*根据需要定义所需数据类型*/
#define INITSIZE 100/*顺序表存储空间的初始分配量*/
typedef struct node{
elemtype *data;/*存储空间基地址*/
int length;/*顺序表长度(已存入元素个数)*/
int lisisize;/*当前容量(能存入元素个数)*/
}sqlist;
地址计算方法
LOC(ai)=LOC(a1)+(i-1)*c 其中c为元素类型占用的存储单元
优点
1->无须为表示表中元素之间的逻辑关系而增加额外的存储空间
2->可以快速存取表中任意位置的元素
缺点
1->插入和删除操作需移动大量元素
2->当线性表长度变化较大时难以确定存储空间容量
3->容易造成空间“碎片”
单链表
定义:用链式存储结构存储的线性表
在逻辑上相邻的元素在物理位置上不要求相邻,为表示结点(数据元素)之间的逻辑关系,分配给每个结点的存储空间分为两部分,一部分存储结点的值,成为数据域;另一部分指向其直接后继的指针,称为指针域。
注:由于最后一个结点没有后继,他的指针域值为NULL,另外还需要一个指针指向第一个结点,成为头指针,头指针(必存在)不等于头结点(不一定存在),头结点的数据域可以为空也可以存储线性表的长度等信息
优点
对于需要频繁插入删除数据元素的应用来说,链表显然在时间复杂度方面优于线性表
单链表的整表创建
头插法与尾插法(略)
我对单链表的数据查找的实现代码
#include <stdlib.h>
#include <stdio.h>//获取列表第i个元素
typedef struct node{
int year;
struct node * next;
}year;
year *new(int n){//创建链表
year *head,*p,*q;
p = head = (year *)malloc(sizeof(year));
printf("请输入%d个年份",n);
for(int i = 1;i <= n;i++){
q = (year *)malloc(sizeof(year));
scanf("%d",&q->year);
p->next = q;
p = q;
}
p->next = NULL;
return head;
}
int locate(year *head,int key){//查找key
int i = 1;
year *p = head->next;
while(p != NULL && p->year != key){
p = p->next;
i++;
}
if(p){
return i;
}else{
return 0;
}
}
void release(year *head){//释放内存
year *q = head->next,*temp;
while(q != NULL){
temp = q;
q = q->next;
free(temp);
}
}
int main(){
int n,key,cx;
year *head;
printf("定义长度为n的单链表,n = ");
scanf("%d",&n);
head = new(n);
printf("请输入你想要定位的年份:");
scanf("%d",&key);
cx = locate(head,key);
if(cx){
printf("%d在该链表中的次序为:%d\n",key,cx);
}else{
printf("链表中不存在%d!!!\n",key);
}
release(head);
return 0;
}
单链表的插入删除
按位插入删除
1->遍历单链表,判断需要插入删除的位数i是否合理,查找出i-1位的结点p
2->插入:创建新结点s,s->data = D(需插入的数据),s->next = p->next,p->next = s,此时p的指针域指向新结点s,s的指针域则指向原i位的结点
删除:创建新结点s,s = p->next,p->next = s->next,此时s为原i位结点,p->next指向原i+1位结点,这时注意释放要删除的结点内存即free(s),为防止野指针的出现,再将s = NULL.
按值删除
与按位删除大同小异,只需在遍历单链表时注意判断数据域的数据是否为需要删除的数据即可。