线性表的存储优点:
无须为表示表中元素之间的逻辑关系而增加额外的存储空间
可以快速地存取表中任意位置的元素
缺点:
插入和删除操作需要移动大量元素
当线性表长度变化较大时,难以确定存储空间的容量
容易造成存储空间的“碎片
链式存储解决了这一问题
线性表的链式存储结构
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以在内 存中未被占用的任意位置。 比起顺序存储结构每个数据元素中需要存储一个位置就可以了。现在链式存储结构中,除了要存储数据 元素信息外,还要存储它的后继元素的存储地址(指针)。
头结点的数据域一般不存储任何信息,是为了操作的统一和方便而设立的,放在第一个元素的结点之 前,其数据域一般无意义(但也可以用来存放链表的长度)。有了头结点,对在第一个元素结点前插入结点 和删除结点时,对于其他的结点的操作就统一了。
头指针是链表中指向第一个结点的指针,若链表有头结点,则是指向头结点的指针,头指针具有标识作 用,所以常用头指针冠以链表的名字(指针变量的名字)。无论链表是否为空,头指针均不为空。头指针是 链表的必要元素。
若线性表需要频繁查找,很少进行插入和删除操作,宜采用顺序存储结构。
若需要频繁插入和删除时,宜采用链式存储结构
具体的分析过程:
链表的操作:
#include <stdio.h>
#include<std>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef int Status;
typedef struct Node{
Elemtype data; //数据域
struct Node *next; //指针域 存储的是下一个结点的地址
}Node,LinkList;
/*
1.初始化 Status init(LinkList *L)
2.头插法插入元素 Status insertHead(LinkList *L,Elemtype e)
3.尾插法插入元素 Status insertTail(LinkList *L,Elemype e)
4.插入元素 Status insert(LinkList *L,int position,Elemtype e)
5.删除头元素 Status deleteHead(LinkList *L,Elemtype *e)
6.删除尾元素 Status deleteTail(LinkList *L,Elemtype *e)
7.删除元素 Status delete(LinkList *L,int position,int *e)
8.获取头元素 Status getHead(LinkList *L,Elemtype *e)
9.获取尾元素 Status getTail(LinkList *L,Elemtype *e)
10.获取位置所在元素 Status get(LinkList *L,int position,Elemtype *e)
11.获取元素所在位置 int locate(LinkList *L,Elemtype e)
12.获取长度 int size(LinkList *L)
13.清空 void clear(LinkList *L)
14.判空列表 Status isEmpty(LinkList *L)
15.打印列表 void show(LinkList *L)
0.退出
*/
Node *R;//尾指针
//1.
Status init(LinkList *L){
L->data=0;
L->next=NULL;
R=L;
for(int i=1;i<=5;i++){
Node *n=malloc(sizeof(Node));
n->data=i;
n->next=L->next;
R->next=n;
if(L->data==0){
R=n;
}
L->data++;
}
return OK;
}
//2.
Status insertHead(LinkList *L,Elemtype e){
Node *n=malloc(sizeof(Node));
n->data=e;
if(L->data==0){ //第一个元素可头插法也可尾插法 第一份元素的头插的话,就是
//目前的尾指针
R=L; //重新初始化尾指针
n->next=R->next;
R->next=n;
R=n;
L->data++;
}else{
n->next=R->next;
R->next=n;
}
L->data++;
return OK;
}
//3.
Status insertTail(LinkList *L,Elemype e){
Node *n=malloc(sizeof(Node));
n->data=e;
n->next=R->next;
R->next=n;
R=n;
L->data++;
return OK;
}
//4.
Status insert(LinkList *L,int position,Elemtype e){
if(position<1||position>L->data+1){
printf(">>>插入位置非法!\n");
return ERROR;
}
if(position==1){
//头插法
insertHead(L,e);
}else if(position==L->data+1){
//尾插法
insertTail(L,e);
}else{
Node *n=malloc(sizeof(Node));
n->data=e;
Node *p=L;
for(int i=1;i<position;i++){
p=p->next;
}
n->next=p->next;
p->next=n;
L->data++;
}
return OK;
}
//5.
Status deleteHead(LinkList *L,Elemtype *e){
if(L->data==0){
printf(">>>单链表为空!\n");
return ERROR;
}
Node *n=L->next;
L->next=n->next;
*e=n->data;
free(n);
L->data--;
if(L->data==0){
R=L;
}
}
//6.
Status deleteTail(LinkList *L,Elemtype *e){
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
Node *p=L;
while(p->next!=R){
p=p->next;
}
Node *n=p->next;
p->next=n->next;
*e=n->data;
R=p;
return OK;
}
//7.
Status delete(LinkList *L,int position,int *e){
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
if(position<1||position>L->data){
printf(">>>删除位置不合法!\n");
return ERROR;
}
if(position==1){
//删头
deleteHead(L,e)
}else if(position==L->data){
//删尾
deleteTail(L,e);
}else{
Node *p=L;
for(int i=1;i<position;i++){
p=p->next;
}
Node *n=p->next;
p->next=n->next;
*e=n->data;
free(n);
L->data--;
}
return OK;
}
//8.
Status getHead(LinkList *L,Elemtype *e){
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
*e=L->next->data;
return OK;
}
//9.
Status getTail(LinkList *L,Elemtype *e){
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
*e=R->data;
return OK;
}
//10.
Status get(LinkList *L,int position,Elemtype *e){
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
if(L->data<1||position>L->data){
printf("位置非法!\n");
return ERROR;
}
Node *p=L;
for(int i=1;i<=position;i++){
p=p->data;
}
*e=p->data;
return OK;
}
//11.
int locate(LinkList *L,Elemtype e){
int position=0;
if(L->data==0){
printf(">>>单列表为空!\n");
return ERROR;
}
Node *p=L->next;
while(1){
if(p==NULL){
printf(">>>无此元素!\n");
return ERROR;
}
if(p->data==e){
return position;
}else{
p=p->next;
position++;
}
}
}
//12.
int size(LinkList *L){:
}
//13.
void clear(LinkList *L){
if(L->data==0){
printf(">>>单列表为空!\n");
return;
}
Node *p;
while(pre->next!==NULL){
p=L->next;
L->next=p->next;
free(p);
L->data--;
}
R=L;
printf("清空完毕!");
}
// 15.
void show(LinkList *L){
if(L-data==0){
printf("[]\n");
return;
}
printf("[");
Node *p=L;
while(1){
p=p->next;
if(p->next==NULL){
printf("%d]\n",p->data);
break;
}else{
printf("%d,"p->data);
}
}
}
void main(){
LinkList L; //创建一个结点 头结点 代表一个单列表
printf("1.初始化\n");
printf("2.头插法插入元素\n");
printf("3.尾插法插入元素\n");
printf("4.插入元素\n");
printf("5.删除头元素 \n");
printf("6.删除尾元素 \n");
printf("7.删除元素 \n");
printf("8.获取头元素 \n");
printf("9.获取尾元素\n");
printf("10.获取位置所在元素 \n");
printf("11.获取元素所在位置\n");
printf("12.获取长度\n");
printf("13.清空\n");
printf("14.判空列表 \n");
printf("15.打印列表 \n");
printf("0.退出\n");
int choice;
int position;
Elemtype e;
while(1){
printf(">>>请选择:");
scanf("%d",&choice);
switch(choice){
case 1:
init(&L);
break;
case 2:
printf(">>>请输入要插入的位置:");
scanf("%d",&e);
insertHead(&L,Elemtype e);
braek;
case 3:
printf(">>>请输入要插入的位置:");
scanf("%d",&e);
insertTail(&L,Elemtype e);
braek;
case 4:
printf(">>>请输入插入的位置:");
scanf("%d",&position);
printf(">>>请输入插入的元素:");
scanf("%d",&e);
insert(&L,position,e);
case 5:
printf(">>>请输入插入的位置:");
scanf("%d",&position);
if(deleteHead(&L,&e)){
printf(">>>删除的元素为%d\n",e);
}
break;
case 6:
if(deleteTail(&L,&e)){
printf(">>>删除的元素为%d\n",e);
}
break;
case 7:
printf(">>>请输入删除的位置:");
scanf("%d",&position);
if(delete(&L,position,&e)){
printf(">>>请输入删除的元素为%d\n:"e);
}
break;
case 8:
if(getHead(&L,&e)){
printf(">>>头元素为%d\n",e);
}
break;
case 9:
if(getTail(&L,&e)){
printf(">>>尾元素为%d\n",e);
}
break;
case 10:
printf(">>>请输入查询的位置:");
scanf("%d",&position);
if(get(&L,position,&e)!=ERROR){
printf(">>>元素为%d\n",e);
}
break;
case 11:
printf(">>>请输入查询的位置:");
scanf("%d",&e);
position=locate(&L,e);
if(position!=ERROR){
printf(">>>元素为%d\n",position);
}
break;
case 12:
printf("长度为%d\n",size(&L));
break;
case 13:
clear(&L);
break;
case 14:
break;
case 15:
show(&L);
break;
}
}
}