以下给出做链表题常用的模板,供大家参考(后附编程测验题)。
废话不多说!直接上代码!手把手教大家写链表题!
链表的C语言定义
#define ElemType int
typedef struct Node /*结点类型定义*/
{
ElemType data;
struct Node *next;
}Node, *LinkList; /*LinkList为结构指针类型*/
尾插法建立带头结点的单链表
LinkList CreateFromTail1() /*将新增的字符追加到链表的末尾*/
{
LinkList L;
Node *r, *s;
int flag = 1;
L = (Node *)malloc(sizeof(Node)); /*为头结点分配存储空间*/
L->next = NULL;
r = L; /*r指针始终动态指向链表的当前表尾*/
while(flag) /*标志,初值为1。输入"$"时flag为0,链表结束*/
{
char c = getchar();
if(c != '$')
{
s = (Node *)malloc(sizeof(Node));
s->data = c;
r->next = s;
r = s;
}
else
{
flag = 0;
r->next = NULL;
}
}
return L;
}
尾插法建立无头结点的单链表
LinkList CreateFromTail2()
{
int n, flag = 1;
LinkList L;
Node *r, *s; //r用来记录链表中的尾结点
L = (Node *)malloc(sizeof(Node)); //先创建第一个结点,给数据域和指针域赋值
char c = getchar();
L->data = c;
L->next = NULL;
r = L; //r记录表中最后一个结点,当前为第一个结点
while(flag)
{
char c = getchar();
if(c != '$')
{
s = (Node *)malloc(sizeof(Node));
s->data = c;
r->next = s;
r = s;
}
else
{
flag = 0;
r->next = NULL;
}
}
r->next = NULL;
return L;
}
头插法建立带头结点的单链表
LinkList CreateFromHead()
{
LinkList L;
Node *s;
int flag = 1;
L = (LinkList)malloc(sizeof(Node));
L->next = NULL;
while(flag)
{
char c = getchar();
if(c != '$')
{
s = (Node *)malloc(sizeof(Node));
s->data = c;
s->next = L->next;
L->next = s;
}
else
{
flag = 0;
}
}
return L;
}
在实际构建单链表的过程中,KLP平台编译运行常常出现时间超限问题,以下给出两种解决办法:(以键盘读入整数为例)
方法一
scanf("%d",&x) != EOF的读入判断,用此方法在DEVC++上运行时,输出会有异常(无输出), 但在KLP平台验证没有问题,答案正确。
尾插法建立带头结点的单链表模板方法一改编版
LinkList CreateFromTail3()
{
LinkList L;
int x;
L = (Node *)malloc(sizeof(Node));
L->next = NULL;
Node *r, *s;
r = L;
while(scanf("%d",&x) != EOF)
{
s = (Node *)malloc(sizeof(Node));
s->data = x;
r->next = s;
r = s;
}
r->next = NULL;
return L;
}
方法二
读入时判断每个元素的后一位是否为空格,如果是空格就继续读入,如果不是空格则退出循环,完成单链表的构建。
尾插法建立带头结点的单链表模板方法二改编版
LinkList CreateFromTail4()
{
LinkList L;
L = (Node *)malloc(sizeof(Node));
Node *p = NULL,*r = L;
char c;
while(1) {
p = (Node *)malloc(sizeof(Node));
scanf("%c",&p->data);
c = getchar();
p->next = NULL;
r->next = p;
r = p;
if(c != ' ')
break;
}
return L;
}
在带头结点的链表中按元素值查找结点
int Locate(LinkList L, ElemType key)
{
Node *p;
int i = 1;
p = L->next; /*从表中第一个结点比较*/
while(p != NULL)
{
if(p->data != key)
p = p->next;
else
break; /*找到结点key,退出循环*/
i++;
}
if(p == NULL)
//printf("ERROR");
return 0;
else
return i;
}
//对于异常的处理可以根据题目要求再自行完善
在带头结点的链表中按序号查找结点
Node *Get(LinkList L, int i)
{
Node *p;
p = L;
int j = 0;
while((p->next != NULL) && (j < i))
{
p = p->next;
j ++;
if(i == j)
return p;
}
return NULL;
}
//对于异常的处理可以根据题目要求再自行完善
在带头结点的链表中插入结点
void InsList(LinkList L, int i, ElemType e)
{
Node *pre, *s;
int k = 0;
pre = L;
while(pre != NULL && k < i - 1)
{
pre = pre->next;
k ++;
}
if(pre == NULL)
{
printf("插入位置不合理!\n");
return;
}
s = (Node *)malloc(sizeof(Node));
s->data = e;
s->next = pre->next;
pre->next = s;
}
//对于异常的处理可以根据题目要求再自行完善
在带头结点的链表中删除结点
bool DelList(LinkList L, int i, ElemType *e)
{
Node *p, *r;
p = L;
int k = 0;
while(p->next != NULL && k < i - 1)
{
p = p->next;
k ++;
}
if(p->next == NULL)
{
printf("删除位置不合理!\n");
return false;
}
r = p->next;
*e = r->data;
p->next = p->next->next;
free(r);
return true;
}
//对于异常的处理可以根据题目要求再自行完善
合并两个有序的带头结点的单链表
LinkList MergeLinkList1(LinkList LA, LinkList LB)
{
Node *pa, *pb;
LinkList LC;
pa = LA->next;
pb = LB->next;
LC = LA;
LC->next = NULL;
LinkList r = LC;
while(pa != NULL && pb != NULL)
{
if(pa->data <= pb->data)
{
r->next = pa;
r = pa;
pa = pa->next;
}
else
{
r->next = pb;
r = pb;
pb = pb->next;
}
}
if(pa)
{
r->next = pa;
free(LA);
return(LC);
}
else
{
r->next = pb;
free(LB);
return(LC);
}
}
以首尾相接方式合并带头结点的单链表
LinkList MergeLinkList2(LinkList LA, LinkList LB)
{
Node *pa, *pb;
pa = LA->next;
pb = LB->next;
LinkList LC;
LC = LA;
LC->next = NULL;
LinkList r = LC;
while(pa != NULL)
{
r->next = pa;
r = pa;
pa = pa->next;
}
while(pb != NULL)
{
r->next = pb;
r = pb;
pb = pb->next;
}
return LC;
}
对一个带头结点的单链表进行从小到大冒泡排序
void BubbleSort(LinkList L)
{
int i ,count = 0, num;
Node *p, *q, *tail;
p = L;
while(p->next != NULL)
{
count++;
p = p->next;
}
for(i = 0; i < count - 1; i++)
{
num = count - i - 1;
q = L->next;
p = q->next;
tail = L;
while(num--)
{
if(q->data > p->data)
{
q->next = p->next;
p->next = q;
tail->next = p;
}
tail = tail->next;
q = tail->next;
p = q->next;
}
}
}
遍历输出带头结点的单链表(元素间以空格隔开)
void PrintLinkList1(LinkList L)
{
Node *r = L->next;
while(r != NULL)
{
printf("%c ",r->data);
r = r->next;
}
}
遍历输出无头结点的单链表(元素间以空格隔开)
void PrintLinkList2(LinkList L)
{
Node *r = L;
while(r != NULL)
{
printf("%c ",r->data);
r = r->next;
}
}
逆置带头结点的单链表
LinkList ReverseLinkList(LinkList L)
{
Node *p1, *p2, *p3;
p1 = (Node *)malloc(sizeof(Node));
p2 = (Node *)malloc(sizeof(Node));
p3 = (Node *)malloc(sizeof(Node));
p1 = L->next;
p2 = p1->next;
p1->next = NULL;
p3 = p2->next;
while(p3 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
L->next = p2;
return L;
}
复制一个带头结点的单链表
LinkList CopyLinkList(LinkList L)
{
LinkList L1;
L1 = (Node *)malloc(sizeof(Node));
L1->next = NULL;
Node *s1, *r1;
L = L->next;
r1 = L1;
while(L != NULL)
{
s1 = (Node *)malloc(sizeof(Node));
s1->data = L->data;
r1->next = s1;
r1 = s1;
L = L->next;
}
r1->next = NULL;
return L1;
}
为便于大家练习,提供链表编程测验题如下(附源代码):