线性表的链式存储结构-单链表

1.预备的基本知识点:

typedef struct Node{
int elem;
struct node * next;
}node,*LinkList;

对于LinkList L: L是指向定义的node结构体的指针,可以用->运算符来访问结构体成员,即L->elem,而(*L)就是个Node型的结构体了,可以用点运算符访问该结构体成员,即(*L).elem;

对于LinkList *L:L是指向定义的Node结构体指针的指针,所以(*L)是指向Node结构体的指针,可以用->运算符来访问结构体成员,即(*L)->elem,当然,(**L)就是Node型结构体了,所以可以用点运算符来访问结构体成员,即(**L).elem;

在链表操作中,我们常常要用链表变量作物函数的参数,这时,用LinkList L还是LinkList *L就很值得考虑深究了,一个用不好,函数就会出现逻辑错误,其准则是:
如果函数会改变指针L的值,而你希望函数结束调用后保存L的值,那你就要用LinkList *L,这样,向函数传递的就是指针的地址,结束调用后,自然就可以去改变指针的值;
而如果函数只会修改指针所指向的内容,而不会更改指针的值,那么用LinkList L就行了;

2.带头结点的单链表代码实现

#include <stdio.h>
#include<stdlib.h>
#include<time.h>

#define MAXSIZE 20  
  
typedef int ElemType;  
  
typedef int Status;  // Status值是函数结果状态代码  
#define OK 1  
#define ERROR 0  
#define TRUE 1  
#define FALSE 0   

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

typedef struct Node *LinkList;

/**
 * 单链表整表创建的算法思路:  (困扰了很久,一直在头指针和头结点没想通 其实初始化的时候是没有头指针初始化,头指针理解为头结点的地址或者第一个结点的地址)
 *           1.声明一指针p和计数器变量i
 *           2.初始化一空链表L,让L的头结点的指针指向NULL,即建立一个带头结点的单链表
 *           3.循环: 1.生成一个新结点复制给p 2.随机生成一数字赋值给p的数据域 3.将p插入到头结点与新结点之间
 */
void CreateListHead(LinkList *L, int n)
{
	LinkList p;
	int i;
	srand(time(0)); // 初始化随机种子,以便让下面的rand()函数每次都不一样(根据time)
    *L = (LinkList)malloc(sizeof(Node));
	(*L)->next = NULL;   // 先建立一个带头结点的单链表
	for(i=0;i<n;i++)
	{
		p = (LinkList)malloc(sizeof(Node));
		p->data = rand()%100+1;
		p->next = (*L)->next;
		(*L)->next = p;
	}
}


void CreateListTail(LinkList *L, int n)
{
	LinkList p,r;
	int i;
	srand(time(0)); // 初始化随机种子,以便让下面的rand()函数每次都不一样(根据time)
	*L = (LinkList)malloc(sizeof(Node)); // 为整个线性表
	r = *L;
	for(i=0; i<n;i++) 
	{
		p = (Node *)malloc(sizeof(Node));
		p->data = rand()%100+1;
		r->next = p;
		r = p;
	}
	r->next = NULL;
}


/**
 * 整个链表的删除
 *     1.声明节点p和q
 *     2.将第一个结点赋值给p
 *     3.循环: 1将下一个结点赋值给q  2.释放p  3.将q赋值给p
 */
Status ClearList(LinkList *L) 
{
	LinkList p,q;
	p = (*L)->next;  // p指向第一个结点
	while(p) 
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*L)->next = NULL;
	return OK;
}

/**
 * 单链表的读取
 *    声明一个指针p指向链表第一个结点,初始化j从1开始
 *    当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累积1
 *    若到链表末尾p为空,则说明第i个结点不存在,否则查找成功,返回结点p的数据
 */
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;
}

void main()
{
    LinkList *head;//定义指针变量  
    //int i,x;定义int变量  
    //CreateListHead(head, 10);//初始化头指针变量,传的是头指针的地址,为的是能得到函数改变头指针变量的值  
    //printf("sizeof=%d  head=%d\n",sizeof(LinkList),head);//测试结构体的占的内存大小,和头指针的值  
    //for(i=1;i<=10;i++){//进行循环  
    //    ListInsert(head,i,i);//进行链表的插入  
    //}  
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值