DS之单链表

单链表概述

线性表的顺序表的优点是随机存取表中的任意元素,但是它的缺点也是明显的,那就是在进行基本操作中的向顺序表中插入和删除数据元素时需要移动大量的元素。因此产生线性表的另一种链式存储结构,也就是单链表。它没有顺序表的弱点,但是也失去了顺序表的优点。

线性表的链式存储结构的特点是用一组任意的存储单元线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素ai与其直接后继数据元素ai+1之间的逻辑关系,对数据元素ai来说,除了存储其本身的信息之外,还需要存储一个指示其直接后继的信息(即直接后继的村相互位置)。这两部分信息组成数据元素ai的存储映像,称为结点。它包括两个域:其中存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域。指针域存储的信息称为指针或链。n个结点的链结成一个链表,即为线性表的链式存储结构。又由于此链表的每个结点中只包含一个指针域,故又称为线性链表或单链表。

下面示例

线性表(zhao,qian,sun,
li, zhou,wu,zheng,wang)

线性链表

头指针 H     
31

存储地址 
数据域 指针域

1         
li      
43

7         
qian    
13

13        
sun      1

19        
wang   
NULL

25        
wu     
37

31        
zhao    
7

37        
zheng   
19

43         
zhou     
2

整个链表的存取必须从头指针开始进行,头指针指示链表中的第一个结点(即第一个数据元素的存储映像)的存储位置。同时由于最后一个数据元素没有直接后继,则线性链表中最后一个结点的指针为“NULL”。

用线性链表表示线性表时,数据元素之间的逻辑关系是由结点中的指针指示的。换句话说,指针为数据元素之间的逻辑关系的映像,则逻辑上相邻的两个数据元素其存储的物理位置不要求紧邻,这种存储结构为非顺序存储映像或链式映像。

通常我们把链表画成用箭头相连接的结点的序列,结点之间的箭头表示链域中的指针。因此上述的示例的线性链表的逻辑状态为:

单链表的存储结构为:

<span style="font-size:18px;">typedef struct LNode//重新定义结构类型为LNode
{
	ElemType date;//定义的结点的数据域
	struct LNode *next;//定义的结点的指针域
}LNode,*LinkLIst//定义的LNode类型的变量LinkList
</span>

有时我们在单链表中的第一个头结点之前附设一个结点,称为头结点。因此带头结点的单链表表示为:

单链表进行插入和删除的图片为:

单链表的基本操作:

0基本操作前的准备

<span style="font-size:18px;">#include <iostream>
using namespace std;
#include <malloc.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
typedef struct LNode//重新定义结构类型为LNode
{
	ElemType data;//定义的结点的数据域
	struct LNode *next;//定义的结点的指针域
}LNode,*LinkList;//定义的LNode类型的变量LinkList</span>

1初始化链表

<span style="font-size:18px;">//1初始化链表
Status InitList(LinkList &L)
{
	L=(LinkList)malloc(sizeof(LNode));
	if(!L)
	{
		return(OVERFLOW);
    }
	L->next=NULL;
	return OK;
}</span>

2销毁链表

<span style="font-size:18px;">//2销毁链表
Status DestoryList(LinkList &L)
{
	LinkList q;
    while(L)
   {
		q=L->next;
        free(L);
        L=q;
	}
    return OK;
}</span>

3清空链表

<span style="font-size:18px;">//3清空链表
Status CLearList(LinkList &L)
{
	LinkList p,q;
	p=L->next;
	while(p)
	{
		q=p->next;
		free(p);
		p=q;
	}
    L->next=NULL;
	return OK;
}</span>

4判断链表是否为空

<span style="font-size:18px;">//4判断链表是否为空
Status ListEmpty(LinkList L)
{
	if (L->next)
	{
		return FALSE;
	}
    else
	{
		return TRUE;
	}
}</span>

5返回链表的长度

<span style="font-size:18px;">Status ListLength (LinkList L)
{
	int i=0;
	LinkList p;
	p=L->next;
	while(p)
	{
		i++;
		p=p->next;
	}
	return i;
}</span>

6返回线性表第i个数据元素的值

<span style="font-size:18px;">//6返回线性表第i个数据元素的值
Status GetElem_L(LinkList L,int i,ElemType &e)//L为带头结点的单链表的头指针
{
    LinkList p=L->next;
	int j=1;//初始化,p指向第一个结点,j为指示器
    while (p&&j<i)//顺时针向后查找,直到p指向第i个元素或p为空
	{
		p=p->next;
		++j;
	}
   if(!p||j>i)
   {
	   return ERROR;//第i个元素不存在
   }
   e=p->data;				//取第i个元素
   return OK;
}</span>

7向链表插入数据元素

<span style="font-size:18px;">//7向链表插入数据元素
Status ListInsert(LinkList &L,int i,ElemType e)
{
   LinkList p=L;
   int j=0;
   while(p&&j<i-1)
   {
	   p=p->next;
	   ++j;
   }
   if(!p||j>i-1)
   {
	   return ERROR;
   }
   LinkList s=(LinkList)malloc(sizeof(LNode));	//生成新结点
   s->data=e;
   s->next=p->next;		//插入L中
   p->next=s;
   return OK;
}</span>

8删除链表中的元素

<span style="font-size:18px;">//8删除链表中的元素
Status ListDelete_L(LinkList &L,int i,ElemType &e)
{
   LinkList p=L;
   int j=0;
   while(p->next&&j<i-1)
   {
	   p=p->next;
	   ++j;
   }
  if (!(p->next)||j>i-1)
  {
	  return ERROR;
  }//删除位置不合理
  LinkList q=p->next;
  p->next=q->next;//删除并释放结点
  e=q->data;
  free(q);
  return OK;
}</span>
时间: 2024-08-04 01:12:46

DS之单链表的相关文章

DS单链表--类实现

题目描述 用C++语言和类实现单链表,含头结点 属性包括:data数据域.next指针域 操作包括:插入.删除.查找 注意:单链表不是数组,所以位置从1开始对应首结点,头结点不放数据 类定义参考 输入 n第1行先输入n表示有n个数据,接着输入n个数据第2行输入要插入的位置和新数据第3行输入要插入的位置和新数据第4行输入要删除的位置第5行输入要删除的位置第6行输入要查找的位置第7行输入要查找的位置 输出 n 数据之间用空格隔开, 第1行输出创建后的单链表的数据 每成功执行一次操作(插入或删除),输

DS单链表--结点交换

题目描述 用C++实现含头结点的单链表,然后实现单链表的两个结点交换位置. 注意不能简单交换两个结点包含数据,必须通过修改指针来实现两个结点的位置交换 交换函数定义可以参考: swap(int  pa, int pb)  //pa和pb表示两个结点在单链表的位置序号 swap (ListNode * p, ListNode * q)  //p和q表示指向两个结点的指针 输入 第1行先输入n表示有n个数据,接着输入n个数据 第2行输入要交换的两个结点位置 第3行输入要交换的两个结点位置 输出 第一

单链表逆置

重写单链表逆置,熟能生巧- #include <iostream> #include <cstdlib> using namespace std; typedef struct List{ int num; struct List *next; }ListNode,*pListNode; void display(ListNode *pHead) { while(pHead) { cout<<pHead->num<<"--"; pH

02 单链表

线性表之链式存储---单链表 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 // 数据结构 6 typedef struct node 7 { 8 int data; 9 struct node *next; 10 }linkList; 11 12 // 创建单链表,并初始化 13 linkList *linkList_init(void) 14 { 15 linkList *l

(单链表)单链表的整体逆序和局部逆序

题目一:将单链表翻转. 思路:有三种方式. 一:用数组存储单链表的值,然后重新逆序赋值,效率较低. 二:利用三个指针,在原来的基础上进行逆序.这种方法比较实用,效率也高. 三:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾.需要新建一个链表,这种方法和第二种差不多. 这里我就写出第二种方法,比较实用. 代码(方法二): struct ListNode { int val; ListNode *next; ListNode(int x) :

[c语言]单链表的实现

一.基础知识:链表(线性表的链式存储结构) (1)特点:逻辑关系相邻,物理位置不一定相邻. (2)分类: a.不带头节点 b.带头节点 (3)单链表的存储结构: typedef struct SListNode {  DataType data;  struct SListNode* next; }SListNode; 二.代码实现(因避开使用二级指针,所以代码中使用了c++中的引用):此处构造的为不带头节点的链表 (1)sList.h   #pragma once typedef int Da

单链表基本操作

//头文件 #pragma once #include <stdio.h> #include <assert.h> #include <malloc.h> #include <stdlib.h> typedef int DateType; typedef struct LinkNode {  DateType _data;  struct  LinkNode* _next; } LinkNode; void PrintList(LinkNode* pHead

C++单链表的创建与操作

链表是一种动态数据结构,他的特点是用一组任意的存储单元(可以是连续的,也可以是不连续的)存放数据元素.链表中每一个元素成为“结点”,每一个结点都是由数据域和指针域组成的,每个结点中的指针域指向下一个结点.Head是“头指针”,表示链表的开始,用来指向第一个结点,而最后一个指针的指针域为NULL(空地址),表示链表的结束.可以看出链表结构必须利用指针才能实现,即一个结点中必须包含一个指针变量,用来存放下一个结点的地址.结点中只有一个next指针的链表称为单链表,这是最简单的链表结构. 首先定义一个

每日一题3:判断单链表是否相交

由于单链表的特殊性,如果某一链表与另一链表相交,那么从相交的节点开始,以后两个链表的每个节点都相同,因此判断两个链表是否相交,只需判断每条链表的最后一个节点是否相同即可! #include "stdafx.h" #include <iostream> using namespace std; struct list_node { int data; list_node* next; }; list_node* CreateList(int datas[],int n) {