单链表整表创建的算法思路:
头插法创建链表
头插法创建链表的函数
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
for (i=0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand() 0 + 1;
p->next = (*L)->next;
(*L)->next = p;
}
}
1. 首先用 *L = (LinkList)malloc(sizeof(Node)); 产生头结点,并使L指向此头结点。再用 (*L)->next = NULL; 即可创建一个带头结点的空链表。
2. 接下来就是循环啦。新增结点都需要用 (LinkList)malloc(sizeof(Node)); 来开辟内存空间。生成结点 p 之后就给 p 的 data 赋随机值,然后再给 p 的 next 赋值。其实这里也就是用前几天讲到的插入操作了。复习一下吧,画个图就很清晰了。
完整的可执行程序(修复插入操作的函数):
#include "stdio.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int Status;
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node;
typedef struct Node *LinkList;
Status InitList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(Node));
if(!(*L))
{
return ERROR;
}
(*L)->next=NULL;
return OK;
}
int ListLength(LinkList L)
{
int i=0;
LinkList p=L->next;
while(p)
{
i++;
p=p->next;
}
return i;
}
Status ListTraverse(LinkList L)
{
LinkList p=L->next;
while(p)
{
visit(p->data);
p=p->next;
}
printf("\n");
return OK;
}
Status visit(ElemType c)
{
printf("-> %d ",c);
return OK;
}
Status GetElem(LinkList L,int i,ElemType *e)
{
int j;
LinkList p;
p = L->next;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if ( !p || j>i )
return ERROR;
*e = p->data;
return OK;
}
int LocateElem(LinkList L,ElemType e)
{
int i=0;
LinkList p=L->next;
while(p)
{
i++;
if(p->data==e)
return i;
p=p->next;
}
return 0;
}
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
for (i=0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand()0+1;
p->next = (*L)->next;
(*L)->next = p;
}
}
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR;
s = (LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete(LinkList *L,int i,ElemType *e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while (p->next && j < i)
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
int main()
{
LinkList L;
Status i;
int j,k,pos,value;
char opp;
ElemType e;
i=InitList(&L);
printf("链表L初始化完毕,ListLength(L)=%d\n",ListLength(L));
printf("\n1.整表创建(头插法) \n2.遍历操作 \n3.插入操作 \n4.删除操作 \n5.获取结点数据 \n6.查找某个数是否在链表中 \n0.退出 \n请选择你的操作:\n");
while(opp != '0')
{
scanf("%c",&opp);
switch(opp)
{
case '1':
CreateListHead(&L,10);
printf("整体创建L的元素(头插法):\n");
ListTraverse(L);
printf("\n");
break;
case '2':
ListTraverse(L);
printf("\n");
break;
case '3':
printf("要在第几个位置插入元素?");
scanf("%d",&pos);
printf("插入的元素值是多少?");
scanf("%d",&value);
ListInsert(&L,pos,value);
ListTraverse(L);
printf("\n");
break;
case '4':
printf("要删除第几个元素?");
scanf("%d",&pos);
ListDelete(&L,pos,&e);
printf("删除第%d个元素成功,现在链表为:\n", pos);
ListTraverse(L);
printf("\n");
break;
case '5':
printf("你需要获取第几个元素?");
scanf("%d",&pos);
GetElem(L,pos,&e);
printf("第%d个元素的值为:%d\n", pos, e);
printf("\n");
break;
case '6':
printf("输入你需要查找的数:");
scanf("%d",&pos);
k=LocateElem(L,pos);
if(k)
printf("第%d个元素的值为%d\n",k,pos);
else
printf("没有值为%d的元素\n",pos);
printf("\n");
break;
case '0':
exit(0);
}
}
}
尾插法创建链表
我们把每次新结点都插在终端结点的后面,这种算法称之为尾插法。
void CreateListTail(LinkList *L, int n)
{
LinkList p,r;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
r=*L;
for (i=0; i < n; i++)
{
p = (Node *)malloc(sizeof(Node));
p->data = rand()0+1;
r->next=p;
r = p;
}
r->next = NULL;
}
与头插法区别下?*L 是头结点,r这里的角色是尾结点,一开始他们是重合的。
对,然后我们需要在结点 r 的后面插入一个结点 p。这很简单,将 r 的 next 指向 p 结点即可。这时要注意,当完成 p 的插入之后,p 会成为新的 r。当完成循环之后,r->next = NULL; 就完成这个单链表。
r=p;是这个意思吧。就是本来r是在元素的结点,可现在它已经不是最后的结点了,现在最后的结点是所以应该要让将p结点这个最后的结点賦值给r。此时r又是最终的尾结点了。循环结束后,那么应该让这个链表的指针域置空,因此有了 r->next = NULL;
完整的程序如下:
#include "stdio.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20
typedef int Status;
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *next;
}Node;
typedef struct Node *LinkList;
Status InitList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(Node));
if(!(*L))
{
return ERROR;
}
(*L)->next=NULL;
return OK;
}
int ListLength(LinkList L)
{
int i=0;
LinkList p=L->next;
while(p)
{
i++;
p=p->next;
}
return i;
}
Status ListTraverse(LinkList L)
{
LinkList p=L->next;
while(p)
{
visit(p->data);
p=p->next;
}
printf("\n");
return OK;
}
Status visit(ElemType c)
{
printf("-> %d ",c);
return OK;
}
Status GetElem(LinkList L,int i,ElemType *e)
{
int j;
LinkList p;
p = L->next;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if ( !p || j>i )
return ERROR;
*e = p->data;
return OK;
}
int LocateElem(LinkList L,ElemType e)
{
int i=0;
LinkList p=L->next;
while(p)
{
i++;
if(p->data==e)
return i;
p=p->next;
}
return 0;
}
void CreateListHead(LinkList *L, int n)
{
LinkList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
for (i=0; i < n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = rand()0+1;
p->next = (*L)->next;
(*L)->next = p;
}
}
void CreateListTail(LinkList *L, int n)
{
LinkList p,r;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
r=*L;
for (i=0; i < n; i++)
{
p = (Node *)malloc(sizeof(Node));
p->data = rand()0+1;
r->next=p;
r = p;
}
r->next = NULL;
}
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p = *L;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR;
s = (LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete(LinkList *L,int i,ElemType *e)
{
int j;
LinkList p,q;
p = *L;
j = 1;
while (p->next && j < i)
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return ERROR;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
int main()
{
LinkList L;
Status i;
int j,k,pos,value;
char opp;
ElemType e;
i=InitList(&L);
printf("链表L初始化完毕,ListLength(L)=%d\n",ListLength(L));
printf("\n1.整表创建(头插法) \n2.整表创建(尾插法) \n3.遍历操作 \n4.插入操作 \n5.删除操作 \n6.获取结点数据 \n7.查找某个数是否在链表中 \n0.退出 \n请选择你的操作:\n");
while(opp != '0'){
scanf("%c",&opp);
switch(opp){
case '1':
CreateListHead(&L,10);
printf("整体创建L的元素(头插法):\n");
ListTraverse(L);
printf("\n");
break;
case '2':
CreateListTail(&L,10);
printf("整体创建L的元素(尾插法):\n");
ListTraverse(L);
printf("\n");
break;
case '3':
ListTraverse(L);
printf("\n");
break;
case '4':
printf("要在第几个位置插入元素?");
scanf("%d",&pos);
printf("插入的元素值是多少?");
scanf("%d",&value);
ListInsert(&L,pos,value);
ListTraverse(L);
printf("\n");
break;
case '5':
printf("要删除第几个元素?");
scanf("%d",&pos);
ListDelete(&L,pos,&e);
printf("删除第%d个元素成功,现在链表为:\n", pos);
ListTraverse(L);
printf("\n");
break;
case '6':
printf("你需要获取第几个元素?");
scanf("%d",&pos);
GetElem(L,pos,&e);
printf("第%d个元素的值为:%d\n", pos, e);
printf("\n");
break;
case '7':
printf("输入你需要查找的数:");
scanf("%d",&pos);
k=LocateElem(L,pos);
if(k)
printf("第%d个元素的值为%d\n",k,pos);
else
printf("没有值为%d的元素\n",pos);
printf("\n");
break;
case '0':
exit(0);
}
}
}