一、线性链表
线性链表的存储结构
typedef int datatype;
typedef struct node
{
datatype data;
struct node *next;
}linklist;
头结点与第一个数据结点一定要区分开来
头结点是整个线性链表的第一个结点,它的数据域可以用来存放线性表的长度等附加信息,也可以不存储任何信息。
线性链表的基本运算
运算 | 函数名 |
---|---|
建立链表 | CREATELIST() |
按序号查找 | GET(head,i) |
插入 | INSERT(p,x) |
删除 | DELETE(\p) |
1.建立链表
1)头插法建表
头插表建立方法是倒序
linklist *CREATELIST_F(int n)
{
int i;
linklist *head;
linklist *s;
head=(linklist*)malloc(sizeof(linklist));
for(i=1;i<=n;i++)
{
s=(linklist*)malloc(sizeof(linklist));
scanf("%d",s->data);
s->next=head->next;
head->next=s;
}
return head;
}
2.按序号查找
//没有考虑链表长度所以p->next!=NULL是保证p不超过最后一个结点
linklist *GET(linklist *head,int i)
{
int j=0
linklist *p;
p=head;
while(p->next!=NULL && (j<i))
{
p=p->next;
j++;
}
if(i==j)
return p;
else
return NULL;
}
3.输出
void OUT(linklist *head)
{
linklist *p;
p=head->next;
while(p)
{
printf("%6d",p->data);
p=p->next;
}
printf("\n");
}
4.插入
1)尾插法
void INSERT_AFTER(linklist *p,datatype x)
{
linklist *s;
s=(linklist*)malloc(sizrof(linklist));
s->data=x;
s->next=p->next;
p->next=s;
}
2).综合应用
void main()
{
linklist *head,*p;
int i,n;
datatype x;
printf("Please input the length of list:\n");
scanf("%d",&n);
printf("Please input the %d datas:\n",n);
head=CREATE_F(n);
OUT(head);
printf("Please input the insert data and order\n")
scanf("%d,%d",&x,&i);
//得到要插入的前一个值的结点指针
p=GET(head,i-1);
if(p)
{
INSERT_AFTER(p,x);
OUT(head);
}
}
5.删除
1)后删
void DELETE_AFTER(linklist *p)
{
p->next=p->next->next;
free(p->next);
}
void DELETE_AFTER(linklist *p)
{
linklist *r;
r=p->next;
p->next=r->next;
free(r);
}
2).综合应用
void main()
{
linklist *P;
int i;
printf("Please input the delete order!\n");
scanf("%d",&i);
p=GET(head,i-1);
if(p)
{
DELETE_AFTER(p);
printf("Data is deleted!\n");
OUT(head);
}
getch();
}
二、循环链表
非循环链表 | 循环链表 |
---|---|
尾指针为,浪费 | 尾指针指向表头 |
指向的是表头(头结点),而不是第一个数据结点,要注意
循环链表和非循环链表的操作基本一致,区别在于判断指针是否指向表尾的条件
循环链表 | 非循环链表 |
---|---|
p!=head | p!=NULL |
p->next!=head | p->next!=NULL |
三、双向链表
1.双向链表的存储结构
typedef struct dnode
{
datatype data;
struct node *prior;
struct node *next;
}dlinklist;
2.插入
void INSERT(linklist *p,datatype x)
{
linklist *s;
s=(linklist*)malloc(sizeof(linklist));
s->data=x;
s->next=p->next;
s->prior=p;
p->next->prior=s;
p->next=s;
}
3.删除
//这里是删除p后面的这个结点
void DELETE(linklist *p)
{
linklist *t;
t=p->next;
p->next=r->next;
p->next->prior=p;
free(t);
}
//这里是删除p这个结点
void DELETE(linklist *p)
{
p->next->prior=p->prior;
p->prior->next=p->next;
free(p);
}