数据结构----单链表

 

数据结构:将数据组织在内存中的一种形式。

 

一、线性存储

特点:除了第一个没有前驱,最后一个没有后继,其他的结点都只有一个前驱和一个后继。

线存储分为顺序存储,链式存储。

顺序存储:在内存中连续的存储空间。如:顺序表。

链式存储:元素在内存中的位置并不连续。如:单链表,双向链表。

二、非线性存储

图:一个数据可能有n个后继,有m个前驱。

树:有一个前驱,n个后继。

二叉树:有一个前驱,两个后继。

对数据的操作有初始化,增删改查,销毁等。

 

数组:大小固定。分配在栈区或堆区。

           数组名记录数组的起始位置。

顺序表:大小可以改变。分配在堆区。

          1. 用elem记录起始位置。

          2.size表示当前顺序表的总大小。

          3.count当前顺序表中元素的个数。

 顺序表特点:1.存储空间连续,并且没有浪费空间。

                      2.插入数据元素时,可能会存在空间的扩充。插入位置之后的元素需要后移。

                      3.删除数据元素时,数据元素也会挪动。

三、单链表

特点:数据存储空间不连续,每一个元素存储一个结点。    结点有数据域和指针域(下一个结点的起始地址)。

单链表带头结点初始化如下:

struct Node
{
	ElemType data;
	struct Node *next;
 };
 
 struct LinkList
 {
 	struct Node head;
 	int count;//结点个数 
 };
 

单链表不带头结点初始化如下:

struct Node
{
	ElemType data;
	struct Node *next;
 }Node;
 
 struct LinkList
 {
 	Node *head;
 	int count;
 };
 

具体代码如下:

LinkList.h

#ifndef __LINKLIST_H
#define __LINKLIST_H

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef int ElemType;

//定义带头结点的单链表
typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node;

typedef struct LinkList
{
	int count;
	struct Node head;
}LinkList, *pList;

void InitLinkList(pList list);  //初始化

void InsertLinkList(pList list, ElemType val, int pos); //插入结点

void InsertHeadLinkList(pList list, ElemType val);  //头插

void InsertTailLinkList(pList list, ElemType val);  //尾插

void DeleteLinkLst(pList list, int pos);  //删除结点

void DeleteHeadLinkLst(pList list);  //头删
 
void DeleteTailLinkLst(pList list);  //尾删

void Show(pList list); //打印输出

void InversionLinkList(pList list); //将单链表逆置

void Destroy(pList list); //销毁

#endif

LinkList.c

#include "LinkList.h"

void InitLinkList(pList list)  //初始化单链表
{
	list->count = 0;
	list->head.next = NULL;
}

static Node *BuyNode(ElemType val, Node *next) //插入结点
{
	Node *s = (Node *)malloc(sizeof(Node));
	assert(s != NULL);

	s->data = val;
	s->next = next;
	return s;
}
void InsertLinkList(pList list, ElemType val, int pos)
{
	assert(list != NULL);

	if( pos < 0 || pos > list->count)
	{
		printf("pos is error\n");
		return ;
	}
	Node *p = &list->head;
	while( pos > 0)
	{
		p = p->next;
		pos --;
	}
	Node *s = BuyNode(val, p->next);
	p->next = s;
	list->count ++;
}

void InsertHeadLinkList(pList list, ElemType val) //头插
{
	InsertLinkList(list, val, 0);
}

void InsertTailLinkList(pList list, ElemType val) //尾插
{
	InsertLinkList(list, val, list->count);
}

void DeleteLinkList(pList list, int pos) //删除结点
{
	assert(list != NULL);
	if( pos < 1 || pos > list->count)
	{
		printf("pos is error\n");
		return;
	}
	Node *p = &list->head;
	while( pos > 1)
	{
		p = p->next;
		pos --;
	}
	Node *s = p->next;
	p->next = s ->next;
	free(s);
	list->count--;
}

void DeleteHeadLinkList(pList list)  //头删
{
	DeleteLinkList(list, 1);
}

void DeleteTailLinkList(pList list) //尾删
{
	DeleteLinkList(list, list->count);
}

void Show(pList list) //输出打印
{
	assert(list != NULL);
	Node *p = &list->head;
	while( p->next!= NULL)
	{
		p = p->next;
		printf("%3d",p->data);	
	}	
	printf("\n");
}

void InversionLinkList(pList list)  //将单链表逆置
{
	assert(list != NULL);
	Node *first = list->head.next;
	Node *middle = first->next;
	Node *last = middle->next;

	while(last->next != NULL)
	{
		if(first == list->head.next)
		{
			first->next = NULL;
		}
		middle->next = first;
		first = middle;
		middle = last;
		last = last->next;
	}
	middle->next = first;
	last->next = middle;
	list->head.next = last;
}

void Destroy(pList list)  //销毁单链表
{
	assert(list != NULL);
	Node *p = &list->head;
	//while(p->next != NULL)
	//采用指针遍历循环会出错,因为每次删除头结点会把指针释放掉(存在问题 继续调试)
	//{
	//    p = p->next;
	// 	  DeleteHeadLinkList(list);		
	//}

	while( list->count > 0)
	{
		DeleteHeadLinkList(list);
	}
	printf("OK\n");
}

main.c    

#include "LinkList.h"

int main()
{
	LinkList list;
	InitLinkList(&list);
	Show(&list);

	for( int i = 0; i < 5; i++)
	{
		InsertLinkList(&list, i * 10, i);
	}

	Show(&list);
	DeleteLinkList(&list,1);
	Show(&list);
	Destroy(&list);
	return 0;
}

 四、顺序表与链表的区别

1.顺序表存储空间连续(虚拟地址空间连续,物理存储空间不连续),链表存储空间不连续。

2.链表相比于顺序表稍微有点浪费空间(每个数据元素存储还需额外的存储指针域)。

3.链表插入或删除数据时,原始数据不需要移动,顺序表反之。

4.顺序表的访问方式简单,速度较快。

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值