数据结构(一)单链表

本文介绍了单链表这一基本数据结构,详细阐述了单链表的存储结构和逻辑特性,包括数据域和指针域的概念。讨论了链表相对于数组的优势,并给出了单链表抽象数据类型的类定义。同时,讲解了节点插入的操作步骤,强调了link断接的顺序。文章还提及了头结点插入和删除的两种方法,分别是头插法和尾插法,以及它们对链表逻辑顺序的影响。

 单链表概念

       单链表是一种最简单的链表表示,也叫做线性链表。用它来表示线性表时,用指针表示节点间的逻辑关系。因此单链表的一个存储结点(node)包括两个部分:数据域(data),指针域(link)。data部分用于存放数据,link部分用于存放指针表示该链表中下一个节点的开始存储地址。

      相比于同为线性结构的数组,链表可以很方便的进行扩充,尽管可能链表中顺序与节点的物理存储顺序不一致,但仍然可以通过指针按照逻辑顺序连接起来。链表的优缺点非常明显,方便进行各种增改删除等操作,但将付出额外的存储空间。

单链表的抽象数据类型类定义

       用结构地构成节点node

 struct node     //链表节点定义
     {
		 int data;   //链表数据类型
		 node *link;
     }*p;            //表头指针定义

      则完整的LinkList.h头文件的写法如下。我写了


class LinkList
{
private:
     struct node     //链表节点定义
     {
		 int data;   //链表数据类型
		 node *link;
     }*p;            //表头指针定义

public:

	 LinkList(void);

        ~LinkList(void);

     //返回表头指针
     node * getHeadPoint();                  
     
     //逐个添加链表元素,尾部添加
     void append( int element );                   
     
     //将链表listB与当前链表合并               
     void merger( LinkList::node * hp_listB, int bFirst);   
     
     //从首部添加链表元素
     void addasFirst( int element );         

     //从指定位置将元素生成结点添加链表,如 从链表第 location == 2个元素后,添加 element == 23
     void addAfter( int element, int location); 

     //删除指定链表元素值大小的所有结点
     void remove( int element );            

     //打印所有链表元素值
     void printAll();                      

     //计算链表长度
     int  size();

     //翻转链表
     void reverse();

     //找出链表中相邻N个结点元素和的最小值并找到所有位置,并将位置信息和最小值打印出来
     void find_smallN();
}
单链表算法

1.节点的插入

       节点插入一定要注意link的断接顺序,先令newnode连接后节点,再令current节点连接newnode。如果先令current节点连接newnode,则将丢失current之后的数据。


newnode->link=current->link;
current->link=newnode;

2.节点的删除

       直接上代码不放图。

     (1)头结点删除

del=first;
first=first->link;
delete del;
    (2)中间或尾部节点的删除(删除current节点的后一个节点)
del=current->link;
current->link=del->link;
delete del;
3.链表的建立

     链表建立分为头插法和尾插法,顾名思义,头插法表示每次插入新节点总是在表的前端进行,这样插入的结果是使链表中个节点中数的逻辑顺序与输入数据的顺序正好相反;尾插法是指每次新节点总是插入到链表的尾端,使链表中各节点数据的逻辑顺序与输入数据的顺序完全一致。

(1)头插法

newnode->link=first->link;
first->link=newnode;
(2)尾插法

       建立last标记链表尾。

last->link=newnode;
last=newnode;
4.单链表其他函数的类实现

#include "stdafx.h"
#include "LinkList.h"
#include<iostream>
using namespace std;

//****************************************************************************************************
//函   数  名: LinkList 
//输 入 参 数: 无           
//返   回  值: 无
//功 能 概 述: 表头指针置空
//备       注: 无参数构造函数
//****************************************************************************************************
LinkList::LinkList(void)
{
	p = NULL;//表头指针置空
}


//****************************************************************************************************
//函   数  名: ~LinkList 
//输 入 参 数: 无          
//返   回  值: 无
//功 能 概 述: 逐个删除链表节点,最后将表头指针置空
//备       注: 无参数析构函数
//****************************************************************************************************
LinkList::~LinkList(void)
{
	node *q;

	//链表为空
	if( p == NULL )
		return;

	//链表不为空
	while( p != NULL )
	{
		q = p->link;
		delete p;
		p = q;
	}
}


//****************************************************************************************************
//函   数  名: getHeadPoint 
//输 入 参 数:  无         
//返   回  值:  链表首部指针
//功 能 概 述:  获得当前链表的首部指针
//备       注:  无
//****************************************************************************************************
LinkList::node* LinkList::getHeadPoint()
{	
	return p;
}

//****************************************************************************************************
//函   数  名: append 
//输 入 参 数: element    待添加链表结点元素值            
//返   回  值:  无
//功 能 概 述:  尾部逐个添加链表结点,表头指针指向第一个结点
//备       注:  无
//****************************************************************************************************
void LinkList::append( int element)
{
	node* q=p,*m;
	m = new node;
	m->data = element;
	if (p == NULL){ m->link = NULL; p = m; p->link = NULL; return; }
	else{
		while (q->link != NULL)
		{
			q = q->link;
		}
		q->link = m;
		m->link = NULL;
	}
}

 //****************************************************************************************************
//函   数  名: merger 
//输 入 参 数: hp_listB    待合并的链表首部指针
//            bFirst     1,b从后合并;0,b从前合并           
//返   回  值:  无
//功 能 概 述:  将链表listB和当前链表合并
//备       注:  无
//****************************************************************************************************
 void LinkList::merger( LinkList::node * hp_listB, int bFirst)
 {
	 node* front, *last;
	 if (bFirst == 1){ front = p; last = hp_listB;}
	 else { front = hp_listB; last = p; }
	 while (front->link != NULL)
		 front = front->link;
	 front->link = last;
 }

//****************************************************************************************************
//函   数  名: addasFirst 
//输 入 参 数: element    待添加链表结点元素值         
//返   回  值: 无
//功 能 概 述: 首部逐个添加链表结点,表头指针指向第一个结点
//备       注: 无
//****************************************************************************************************

void LinkList::addasFirst(int element)
{
	node* q;
	q = new node;
	q->data = element;
	q->link = p;
	p = q;
}


//****************************************************************************************************
//函   数  名: addAfter 
//输 入 参 数:  location   结点添加后,成为第location+1个结点
//             element    待添加链表结点元素值
//返   回  值: 无
//功 能 概 述: 指定位置逐个添加链表结点,表头指针指向第一个结点
//备       注: 如果链表长度小于插入位置,需要提示信息 如 There are less than 10 nodes .
//****************************************************************************************************
void LinkList::addAfter(int location, int element)
{
	int i;
	node* add = p, *q = p;
	add = new node;
	add->data = element;
	for (i = 1; i < location; i++){
		if (q->link == NULL&&i < location){
			cout << "There are less than" << location << "nodes";
			return;
		}
		q = q->link;
		}
	add->link = q->link;
	q->link = add;
	
}


//**************************************************************************************************** 
//输 入 参 数: element    待删除链表结点元素值           
//返   回  值: 无
//功 能 概 述: 删除指定元素大小的所有结点
//备       注: 如果 待删除的元素不存在 需要提示信息 如 Element 12 is not found
//****************************************************************************************************
void LinkList::remove(int element)
{
	node* q = p, *m=q;
	int i = 0;
	
	while (q->link != NULL)
	{	
		if (q->data == element)
		{
			if (q == p)
                           { 
                             i++;
                             p = q->link; 
                             delete q; 
                             q = p; 
                           }
			else{
			i++;
			m->link = q->link;
			delete q;
			q = m->link;}
		}
		m = q;
		q = q->link;
			
	}
	if (q->data == element)
	{
		if (q == p)
                    { 
                       i++;
                       p = q->link; 
                      delete q; 
                      q = p; 
                    }
		else{
			i++;
			m->link = q->link;
			delete q;
			q = m->link;
		}
	}
	if (i == 0){
		cout << "Element " << element << " is not found."; return;
	}
}

//****************************************************************************************************
//函   数  名: printAll 
//输 入 参 数:  无       
//返   回  值:  无
//功 能 概 述: 将链表各结点值逐个打印出来
//备       注: 无
//****************************************************************************************************
void LinkList::printAll()
{
	node*q = p;
	while (q != NULL){
		cout << q->data<<endl;
		q = q->link;
	}	
}

//****************************************************************************************************
//函   数  名: size 
//输 入 参 数:  无       
//返   回  值:  链表长度
//功 能 概 述: 计算链表长度
//备       注: 无
//****************************************************************************************************
int LinkList::size()
{
	int i=1;
	node*q = p;
	if (p == NULL)return 0;
	else{
		while (q->link != NULL){
			q = q->link;
			i++;
		}
		return i;
	}
}

//****************************************************************************************************
//函   数  名: reverse 
//输 入 参 数:  无        
//返   回  值:  无
//功 能 概 述:  将当前链表翻转
//备       注: 无
//****************************************************************************************************
void LinkList::reverse()
{
	node*q = p->link, *m = q->link, *n = p;
	q->link = n;
	n->link = NULL;
	while (m->link!=NULL)
       {
		n = q;
		q = m;
		m = m->link;
		q->link = n;
	}
	m->link = q;
	p = m;
}
//****************************************************************************************************
//函   数  名: find_ smallN
//输 入 参 数:  无        
//返   回  值:  无
//功 能 概 述:  找出链表中相邻N个结点元素和的最小值并找到所有位置,并将位置信息和最小值打印出来
//备       注: 无
//****************************************************************************************************
void LinkList::find_smallN()
{
	int length = 1, m, k = p->data, num=1, firstnode=1;
	node*q = p;
	if (p == NULL)
             { 
               cout << "The linklist is null"; 
               return; 
             }
	else{
		while (q->link != NULL)
                {
			q = q->link;
			length++;
		}
	}
	q = p;
	node*fir = p, *sec = p;
	for (int i = 1; i <= length; i++)
	{
		for (int j = 1; j <= length-i+1; j++)
		{
			sec = fir;
			m = 0;
			for (int l = 1; l <= j; l++)
			{
				m = sec->data + m;
				sec = sec->link;
			}
			if (m < k){
				k = m;
				num = j;
				firstnode = i;
			}

		}
		fir = fir->link;
	}
	if (num == 1)
        cout << "相邻" << num << "个结点元素和的最小值为" << k << "位置是第" << firstnode << "结点" << endl; 
	else
	cout << "相邻" << num << "个结点元素和的最小值为" << k << "位置是第" << firstnode << "-" << firstnode + num-1 << "结点" << endl;
	

}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值