链表在存储线性表时,不要求逻辑上相连的数据元素在物理位置上也相邻,所以在插入和删除操作的时候,不需要移动元素,只需要修改指针即可。
具体实现如下:
//线性表实现——链表(设置头结点)
#include <stdio.h>
#include <stdlib.h>
#define ElementType int
/*
1 2 3 4 5 6 -1 程序测试数据
*/
typedef struct node{
ElementType data;
struct node *next;
}L;
typedef L* List;
List Make_List_head( ); //头插法创建表
List Make_List_tail( ); //尾插法创建表
List find( ElementType x, List ptrl ); //查找元素,返回下标,若没找到返回-1
void insert( ElementType x, int i, List ptrl ); //插入函数,在第i个位置插入新元素
void Delete( int i, List ptrl ); //删除线性表中第i个元素
int length ( List ptrl ); //返回表长(即线性表中数据元素的个数)
List find_k( int i, List ptrl ); //返回线性表中第i个元素
int Empty( List ptrl ); //判断表空,如果表空,返回0;表不空,返回1
void PrintList( List ptrl, int m, int n ); //打印从位置m到位置n的所有元素
void DestoryList( List ptrl ); //销毁链表
int main ( void )
{
List ptrl;
ptrl = Make_List_tail( );
if( !Empty( ptrl ) )
printf( "表空\n" );
int len = length( ptrl );
printf( "表长len = %d\n", len );
PrintList( ptrl, 1, len );
int x = 731;
insert( x, 5, ptrl );
PrintList( ptrl, 1, len + 1 );
Delete( 4, ptrl );
PrintList( ptrl, 1, len );
return 0;
}
List Make_List_head( )
{
List ptrl, s;
ptrl = ( List )malloc( sizeof( L ) );
if( ptrl == NULL ){
printf( "申请空间出错\n" );
exit(0);
}
ptrl -> next = NULL;
ElementType x;
scanf( "%d", &x );
while( x != -1 ){ //输入以-1为结束标志
s = ( List )malloc( sizeof( L ) );
if( s == NULL ){
printf( "申请空间出错\n" );
exit(0);
}
s -> next = ptrl -> next;
ptrl -> next = s;
s -> data = x;
scanf( "%d", &x );
}
return ptrl;
}
List Make_List_tail( )
{
List ptrl, s, p;
ptrl = ( List )malloc( sizeof( L ) );
if( ptrl == NULL ){
printf( "申请空间出错\n" );
exit(0);
}
ptrl -> next = NULL;
ElementType x;
scanf( "%d", &x );
p = ptrl;
while( x != -1 ){
s = ( List )malloc( sizeof( L ) );
if( s == NULL ){
printf( "申请空间出错\n" );
exit(0);
}
s -> data = x;
p -> next = s;
p = s;
scanf( "%d", &x );
}
p -> next = NULL;
return ptrl;
}
List find_k( int i, List ptrl )
{
int k = 1;
List p = ptrl -> next;
if( i == 0 )
return ptrl;
if( i < 1 )
return NULL;
while( k < i && p != NULL ){
k++;
p = p -> next;
}
return p;
}
List find( ElementType x, List ptrl )
{
List p = ptrl -> next;
while( p -> data != x && p -> next != NULL ){
p = p -> next;
}
return p;
}
void insert( ElementType x, int i, List ptrl )
{
List p = find_k( i - 1, ptrl );
if( p == NULL ){
printf( "查找位置错误\n" );
exit(0);
}
List s;
s = ( List )malloc( sizeof( L ) );
if( s == NULL ){
printf( "申请空间出错\n" );
exit(0);
}
s -> data = x;
s -> next = p -> next;
p -> next = s;
}
void Delete( int i, List ptrl )
{
List p = find_k( i - 1, ptrl );
if( p == NULL ){
printf( "查找位置错误\n" );
exit(0);
}
List s;
s = p -> next;
p -> next = s -> next;
free( s );
}
int length ( List ptrl )
{
int len = 0;
while( ptrl -> next != NULL ){
len++;
ptrl = ptrl -> next;
}
return len;
}
int Empty( List ptrl )
{
if( ptrl -> next == NULL )
return 0;
else
return 1;
}
void PrintList( List ptrl, int m, int n )
{
List p, q;
p = find_k( m, ptrl );
q = find_k( m, ptrl );
int i, len = length( ptrl );
for( i = m; i <= n; i++ ){
printf( "%d ", p -> data );
p = p -> next;
}
printf( "\n" );
}
void DestoryList( List ptrl )
{
List s, p;
s = ptrl -> next;
ptrl -> next = NULL;
while( s != NULL ){
p = s -> next;
free( s );
s = p;
}
}
相比于顺序表存储的方式:
(1)单链表是非随机存取的存储结构,不能根据序号直接找到某个特定的节点,一般需要从表头开始遍历,依次查找,而顺序表可以随机存取;
(2)采用顺序表实现的单链表数据元素之间既在逻辑关系上相邻,也在物理位置上相邻,而链式结构实现的单链表逻辑关系相邻的数据元素在物理位置上不一定相邻,,这解决了顺序表需要大量连续存储空间的缺点;
(3)顺序表的方法的存储密度高,而链表结构由于在每个节点中需要存储指针域,所以相对于线性表而言存储密度低;
(4)在插入和删除操作中,顺序表平均需要移动一半的元素,而链表只需要修改相应的指针即可;
(5)在空间分配上链表实现更加高效和灵活。