关于单链表的故事实在太多了,孰能生巧。今天有个同学说怎样用C方式(不用类)的形式重写单链表的列表。刚开始不以为然,可后来发现其实不那么简单啊。复习了严老师的数据结构后,于是就有了今天的第一个练习。
#include <iostream>
using namespace std;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
LNode * next;
} *SLink;
LNode *p, *q;
int j;
SLink InitList( SLink & L ) // 初始化链表
{
// 创建一个带头结点的空链表,L 为指向头结点的指针
L = new LNode;
if( !L ) exit(1); // 存储空间分配失败
L->next = NULL;
return L;
}
void DestroyList( SLink & L ) // 销毁链表
{
// 从头结点开始往后删除。 最后把 L 置 NULL,以防万一。
while( L )
{
p = L;
L=L->next;
delete p;
}
L = NULL;
}
bool GetElem( SLink L, int pos, ElemType & e ) // 取元素
{
// 因为有头结点,pos 不从 0 开始计数, 1 就表示第一个位置。
p = L->next; j = 1;
// 定位pos位置的循环的跳出条件为 : p 为空 或者 已到 pos 位置。
while( p && j<pos )
{
p = p->next; j++;
}
if( !p || j>pos ) return false; // 判断 pos 的非法值输入
e = p->data;
return true;
}
bool ListInsert( SLink & L, int pos, const ElemType & e ) // 若1≤pos≤LengthList(L)+1,则在指针L指向头结点的单链表
{
p = L; j=0;
while( p && j<pos-1 )
{
p = p->next; j++;
}
if( !p || j>pos-1 ) return false; // 参数不合法
q = new LNode;
if( !q) exit(1);
q->data = e;
q->next = p->next; p->next = q;
return true;
}
bool ListDelete( SLink & L, int pos, ElemType & e )
{
// 对插入而言,只要"前驱"存在即可,而对删除而言,不仅"前驱"要存在,被删结点也必须存在。
p = L; j=0;
while( p->next && j<pos-1 )
{
p = p->next; j++;
}
if( !(p->next) || j>pos-1) return false;
q = p->next;
p->next = q->next;
e = q->data; delete q;
return true;
}
// 逆序创建链表
SLink CreateList_R( int a[], int n )
{
SLink L = new LNode;
if( !L ) exit(1);
L->next = NULL;
for( int i =n; i>0; --i )
{
p = new LNode;
if( !p ) exit(1);
p->data = a[i-1];
p->next = L->next; L->next = p; // // 插入在头结点之后
}
return L;
}
//顺序创建链表
SLink CreateList_S( int a[], int n )
//因为每个新生成的结点的插入位置在表尾,则算法中必须维持一个始终指向已建立的链表表尾的指针。
{
SLink L = new LNode;
if( !L ) exit(1);
L->next = NULL;
LNode * tail = L;
for( int i=0; i<n ; ++i )
{
p = new LNode;
if( !p ) exit(1);
p->data = a[i];
tail->next = p; tail = p;
}
tail->next = NULL;
return L;
}
void print( const SLink & L )
{
p = L->next;
while( p ) { cout<<p->data<<" "<<flush; p = p->next; }
cout<<endl;
}
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
SLink zp1= CreateList_R( a, 5 ); // 逆序生成
print( zp1);
SLink zp2= CreateList_S( a, 5 ); // 顺序生成
print( zp2);
int temp;
ListInsert( zp1, 1, 6 );
print( zp1);
ListDelete( zp1, 6, temp);
print( zp1 );
GetElem( zp1, 2, temp ); // 取值
cout<<temp<<endl;
cin.get();
}