您的位置:首页 > 编程语言 > C语言/C++

C语言实现单链表

2013-12-31 20:07 363 查看
定义:n个结点链结成一个链表,即为线性表(a1,a2,...,an)的链式存储结构,因为链表的每个结点中只包含一个指针域,所以叫做单链表。

头指针:链表中第一个结点的存储位置叫做头指针。

头结点:单链表的第一个结点前附设一个结点,称为头结点。‘

 

可用C语言中的结构指针来描述单链表的存储结构,如下:

struct Node
{
ElemType data;
struct Node * next;
};
typedef struct Node * LinkList;


 由上可知,结点由存放数据元素的数据域和存放后继结点地址的指针域组成。

 

单链表的整表创建

创建一个带头结点的单链表

方法一:头插法即始终让新结点在第一的位置

代码如下

void CreateListHead(LinkList *L,int n)
{
LinkList p;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(struct Node));
(*L)->next = NULL;
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(struct Node));
p->data = rand() % 100 + 1;
p->next = (*L)->next;
(*L)->next = p;
}
}


方法二:尾插法即新结点总是在最后

代码如下:

 

/随机产生n个元素的值,建立带表头结点的单链表L(尾插法)
void CreateListTail(LinkList *L, int n)
{
LinkList p, r;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(struct Node));
r = *L;
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(struct Node));
p->data= rand()%100+1;
r->next = p;
r = p;
}
r->next = NULL;
}

 

单链表的读取

/*操作结果:用e返回L中第i个数据元素的值*/
int 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 0;
}

*e = p->data;
return 1;
}


时间复杂度为O(n)

 

单链表的插入

/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
int 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 0;
}

s = (LinkList)malloc(sizeof(struct Node));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}


单链表的删除

/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1*/
int 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 0;
}

q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return 1;
}


单链表插入和删除分析:它们的时间复杂度都是O(n),但是如果要在一个位置插入多个元素,对于单链表只需第一次找到插入的位置,此时为O(n),接下来只是简单的赋值移动指针,时间复杂度都是O(1)。因此对于插入或者删除数据越频繁的操作,单链表的效率优势越是明显。

 

完整代码如下

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
typedef int ElemType;

struct Node { ElemType data; struct Node * next; }; typedef struct Node * LinkList;
int main()
{
void CreateListHead(LinkList *L, int n);
void CreateListTail(LinkList *L, int n);
int GetElem(LinkList L, int i, ElemType *e);
int ListInsert(LinkList p, int i, ElemType e);
int ListDelete(LinkList p, int i, ElemType *e);
LinkList *L = (LinkList *)malloc(4);
int n = 5;
CreateListTail(L, n);

ListInsert(*L, 3, 1000);

ElemType *e = &n;
int i = 3;
GetElem(*L, i, e);
printf("%d\n", *e);

ListDelete(*L, 3, e);
printf("%d", *e);
}

void CreateListHead(LinkList *L,int n) { LinkList p; int i; srand(time(0)); *L = (LinkList)malloc(sizeof(struct Node)); (*L)->next = NULL; for (i = 0; i < n; i++) { p = (LinkList)malloc(sizeof(struct Node)); p->data = rand() % 100 + 1; p->next = (*L)->next; (*L)->next = p; } }

//随机产生n个元素的值,建立带表头结点的单链表L(尾插法)
void CreateListTail(LinkList *L, int n)
{
LinkList p, r;
int i;
srand(time(0));
*L = (LinkList)malloc(sizeof(struct Node));
r = *L;
for (i = 0; i < n; i++)
{
p = (LinkList)malloc(sizeof(struct Node));
p->data= rand()%100+1;
r->next = p;
r = p;
}
r->next = NULL;
}

/*操作结果:用e返回L中第i个数据元素的值*/ int 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 0; } *e = p->data; return 1; }

/*操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1*/
int 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 0;
}

s = (LinkList)malloc(sizeof(struct Node));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}

/*操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1*/ int 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 0; } q = p->next; p->next = q->next; *e = q->data; free(q); return 1; }


参考文献:大话数据结构
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息