数据结构:单链表

本文详细介绍了链式存储结构及其优势,重点讲解了单链表的概念,它是由节点构成,每个节点包括数据域和指针域指向后继节点。讨论了单链表与顺序表的区别,并给出了单链表头插、尾插的操作,以及相关代码实现。

1、链式存储结构:在链式存储的过程中,每个元素Node不仅包含元素本身的信息,还包含元素之间的逻辑信息。前驱结点包含后继结点的地址信息(指针域),可以很方便的找到后继结点的位置。

2、链表:通过一组任意的存储单元来存储线性表中的数据元素,由一个个结点构成。

3、单链表:每个结点除包含数据域外,只设置一个指针域,来指向后继结点,这样构成的链表就是单链表。

      单链表是一种链式存取的数据结构,用一组任意地址空间(地址空间即存储单元)来存放线性表的数据元素。单链表中的数据是以节点的形式来表示,而节点是用结构体来描述,每个节点都是由元素和指针构成,即该结构体中包含两个成员变量:存放元素的成员变量和存放下一个节点地址的成员变量。单链表的节点结构为如下所示:

4、链表与顺序表的区别:

顺序表的特点为:逻辑相邻的两节点其物理地址也是相邻的;链表的特点为:逻辑相邻的两节点其物理地址不相邻。顺序表的存储方式是:节点元素连续存放在存储单元;链表的存储方式是:节点元素随机存放在存储单元。

5、单链表的结构:

6、单链表的头插

 

//头插法
bool Insert_head(List plist,int val)
{
	Node *p = (Node *)malloc(sizeof(Node));  //p即为新节点
	p->data = val;                           //p的data域设为val
	p->next = plist->next;                   //将plist存储的下一个节点的地址赋值给p
	plist->next = p;                         //将头结点的下一个节点设置为p
	return true;
}

7、单链表的尾插

 

 

//尾插法
bool Insert_tail(List plist,int val)
{
	//第一步,设置新节点
	Node *p = (Node *)malloc(sizeof(Node));
	assert(p != NULL);
	if(p == NULL)
	{
		return false;
	}
	p->data = val;
	//第二步,找尾节点
	Node *q;
	for(q = plist;q->next != NULL;q = q->next);
	//将p插入到q的后面
	p->next = q->next;
	q->next = p;
	return true;
	
}

8、完整代码

(1)list.h:

#pragma once
//带头节点的单链表
//单链表尾节点的next为NULL
//List为一条链表;Node *一个节点的地址
typedef struct Node
{
    int data; //数据
    struct Node *next;//下一个节点的地址
}Node,*List;//List == Node *

//初始化
void InitList(List plist);

//头插法
bool Insert_head(List plist,int val);

//尾插法
bool Insert_tail(List plist,int val);

//在pos下标插入数据val
bool Insert_pos(List plist,int pos,int val);

//查找,找到返回节点地址,没有找到返回NULL
Node *Search(List plist,int key);

//删除第一个key对应的节点
bool Delete(List plist,int key);

//删除第一个数据节点,并通过rtval获得删除的值
bool Delete_head(List plist,int *rtval);

//删除最后一个数据节点,并通过rtval获得删除的值
bool Delete_tail(List plist,int *rtval);

//获取长度,统计数据节点的个数
int GetLength(List plist);

//判空
bool IsEmpty(List plist);


//销毁所有节点
void Destroy(List plist);

//打印
void Show(List plist);

(2)list.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "list.h"

//初始化
void InitList(List plist) //List == Node *,plist即为头结点
{
	assert(plist != NULL);
	plist->next = NULL;

}

//头插法
bool Insert_head(List plist,int val)
{
	Node *p = (Node *)malloc(sizeof(Node));  //p即为新节点
	p->data = val;                           //p的data域设为val
	p->next = plist->next;                   //将plist存储的下一个节点的地址赋值给p
	plist->next = p;                         //将头结点的下一个节点设置为p
	return true;
}

//尾插法
bool Insert_tail(List plist,int val)
{
	//第一步,设置新节点
	Node *p = (Node *)malloc(sizeof(Node));
	assert(p != NULL);
	if(p == NULL)
	{
		return false;
	}
	p->data = val;
	//第二步,找尾节点
	Node *q;
	for(q = plist;q->next != NULL;q = q->next);
	//将p插入到q的后面
	p->next = q->next;
	q->next = p;
	return true;
	
}

//在pos下标插入数据val
bool Insert_pos(List plist,int pos,int val)
{
	//判断输入的位置是否正确
	if(pos < 0)
	{
		return false;
	}

	//找到pos位置的前一个节点
	Node *q;
	int i;
	for(i = 0,q = plist;q->next != NULL && i < pos;q = q->next,i++);

	Node *p = (Node *)malloc(sizeof(Node));
	p->data = val;
	p->next = q->next;
	q->next = p;
	return true;
}

//查找,找到返回节点地址,没有找到返回NULL
Node *Search(List plist,int key)
{
	assert(plist != NULL);
	for(Node *p = plist->next;p->next != NULL;p = p->next)
	{
		if(p->data == key)
		{
			return p;
		}
	}
	return NULL;
}

//查找key的前驱节点
static Node *SearchPri(List plist,int key)
{
	for(Node *p = plist;p != NULL;p = p->next)
	{
		if(p->next->data == key)
		{
			return p;
		}
	}
	return NULL;
}

//删除第一个key对应的节点
bool Delete(List plist,int key)
{
	Node *p = SearchPri(plist,key);
	if(p == NULL)
	{
		return false;
	}
	Node *q = p->next;  //q指向要删除的节点
	p->next = q->next;  //将q从链表中剔除
	free(q);            //释放内存

	return true;
}

//删除第一个数据节点,并通过rtval获得删除的值
bool Delete_head(List plist,int *rtval)
{
	if(plist->next  == NULL)
	{
		return false;
	}

	Node *p = plist->next;

	if(rtval == NULL)
	{
		*rtval = p->data;
	}

	plist->next = p->next;
	free(p);
	return true;
}

//删除最后一个数据节点,并通过rtval获得删除的值
bool Delete_tail(List plist,int *rtval)
{
	assert(plist != NULL);
	if(plist == NULL)
	{
		return false;
	}
	if(plist->next  == NULL)
	{
		return false;
	}
	Node *p = plist;//p为要删除的节点
	Node *q = p;   //q保存p的上一节点
	while(p->next!= NULL)
	{
		q = p;
		p = p->next;
	}
	if(rtval != NULL)
	{
		*rtval = q->data;
	}
	
	free(p);
	q->next = NULL;

	return true;

}

//获取长度,统计数据节点的个数
int GetLength(List plist)
{
	int count = 0;
	for(Node *p = plist->next;p != NULL;p = p->next)
	{
		count++;
	}
	return count;
}

//判空
bool IsEmpty(List plist)
{
	if(plist->next == NULL)
	{
		return true;
	}
	return false;
}


//销毁所有节点
void Destroy(List plist)
{
	Node *p;
	while(plist -> next != NULL)
	{
		p = plist->next;
		plist->next = p->next;
		free(p);
	}
}

//打印
void Show(List plist)
{
	if(IsEmpty(plist))
	{
		return;
	}
	for(Node *p = plist->next;p != NULL;p = p->next)
	{
		printf("%d ",p->data);
	}
	printf("\n");
}

(3)main.cpp:

#include <stdio.h>
#include "list.h"

int main()
{
    Node head;//CreateList();
    InitList(&head);

    //Node p;//Node *p
    //InitList(&p);
    for(int i=0;i<10;i++)
    {
		Insert_tail(&head,i);
	//Insert_head(&head,i);
    }

    Show(&head);
    
    Insert_pos(&head,0,-30);
	Show(&head);

    Insert_pos(&head,5,30);
	Show(&head);

    Insert_pos(&head,12,300);
	Show(&head);

    Insert_pos(&head,14,3000);
    Show(&head);

    Delete(&head,30);
	Show(&head);

    Delete(&head,-30);
	Show(&head);

    Delete(&head,300);
    Show(&head);
	
	int a;
	int *rtval = &a;
	Delete_tail(&head,rtval);
	Show(&head);

    Destroy(&head);
    Destroy(&head);
	Show(&head);

    return 0;
}

(4)OOP的实现:

class Link
{
public:
    Link()
    {
        phead=new Node;
    }
    ~Link()
    {
        Node*pcur=phead;
        while(pcur!=NULL)
        {
            phead=phead->pnext;
            delete phead;
            pcur=phead;
        }
    }
    void inserthead(int val)
    {
        Node*pcur=new Node(val);
        pcur->pnext=phead->pnext;
        phead->pnext=pcur;
    }
    void inserttail(int val)
    {
        Node*pcur=phead;
        while(pcur->pnext!=NULL)
        {
            pcur=pcur->pnext;
        }
        pcur->pnext=new Node(val);
    }
    void deleteNode(int val)
    {
        Node*pcur1=phead;
        Node*pcur2=phead->pnext;
        while(pcur2!=NULL)
        {
            if(pcur2->data==val)
            {
                pcur1->pnext=pcur2->pnext;
                delete pcur2;
                pcur2=pcur1->pnext;
            }
            else
            {
                pcur1=pcur2;
                pcur2=pcur2->pnext;
            }
        }
    }
    void show()
    {
        Node*pcur=phead->next;
        while(pcur!=NULL)
        {
            cout<<pcur->data<<" ";
            pcur=pcur->pnext;
        }
    }
 private:
    class Node
    {
     public:
        Node(int data):pdata(data),pnext(NULL){}
        int pdata;
        Node*pnext;
    };
    Node*phead;
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值