线性表的顺序存储的特点是,在逻辑关系上相邻的两个元素在物理位置上也是相邻的,因此可以随机存取表中任一元素。但是,当经常做插入和删除操作运算时,则需要移动大量的元素,而采用链式存储结构就可以避免这些移动。
用C语言中的结构类型描述线性表的链式存储结构如下:
typedef struct node{
Datatype data;
struct node *next;
}ListNode;
typedef ListNode *LinkList;
ListNode *p;
LinkList head;
一、单链表基本运算
1、建立单链表
1.1 头插法建表
LinkList CreateListF()
{
LinkList head;
ListNode *p;
char ch;
head = NULL;
ch = getchar();
while(ch!='\n')
{
p = (ListNode *)malloc(sizeof(ListNode));
p->data = ch;
p->next = head;
head = p;
ch = getchar();
}
return head;
}
1.2 尾插法建表
LinkList CreateListR()
{
LinkList head = (ListNode *)malloc(sizeof(ListNode));
ListNode *p, *r;
DataType ch;
r = head;
while((ch=getchar())!='\n')
{
p = (ListNode *)malloc(sizeof(ListNode));
p->data = ch;
r->next = p;
r = p;
}
r->next = NULL;
return head;
}
2、查找运算
2.1 按节点序号查找
ListNode * GetNodei(LinkList head, int i)
{
ListNode *p;
int j;
p = head->next;
j = 1;
while(p!=NULL && j<i)
{
p = p->next;
++j;
}
if(j==i)
return p;
else
return NULL;
}
2.2 按节点值查找
ListNode * LocateNodek(LinkList head, DataType K)
{
ListNode *p=head->next;
while(p&&p->data!=k)
p = p->next;
return p;
}
3、插入运算
void InsertList(LinkList head,int i, DataType k)
{
ListNode *p, *s;
int j;
p=head;
j=0;
while(p!=NULL && j<i)
{
p=p->next;
++j
}
if(p==NULL)
{
printf("ERROR\n");
return;
}
else
{
s = (ListNode *)malloc(sizeof(ListNode));
s->data = x;
s->next =p->next;
p->next = s;
}
}
4、删除运算
DataType DeleteList(LinkList head, int i)
{
ListNode *p, *s;
DataType x;
int j;
while(p!=NULL && j<i-1)
{
p=p->next;
++j;
}
if(p==NULL)
{
printf("位置错误\n");
exit(0);
}
else
{
s = p->next;
p ->next = s->next;
x = s->data;
free(s);
return x;
}
}
二、双向链表
双向链表重点关注删除算法,如下:
DataType DLDelete(DLNode *p)
{
p->prior->next = p->next;
p->next->prior=p->prior;
free(p);
return x;
}
注:p指向当前节点