数据结构基础--单链表

单链表:

(一):单链表相关知识点理解
单链表是一种链式存取的数据结构。用一组地址任意的存储单元存放线性表中的数据元素。 链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置)。
其中元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
②链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))

如下图所示为单链表的存储结构图:
在这里插入图片描述
这里每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。 链表由头指针唯一确定,单链表可以用头指针的名字来命名。
终端结点无后继,故终端结点的指针域为空,即NULL。

(二):单链表相关操作
单链表的基本操作包括:建立,初始化,插入,删除,查找,判空,逆置,销毁等,在进行基本操作时 ,需要注意:

   1.是否依赖于前驱信息,从而导致初始化值不同。
   2.在插入,删除等操作时,应先考虑是否将当前与后面的节点关联起来(以防数据丢失),再关联当前结点与前一个结点。

以下为相关代码块。


//for(p=plist;p->next!=NULL;p=p->next)
//依赖于前驱信息(删除/尾插法/查找前驱信息/查找)

//for(p=plist->next;p!=NULL;p=p->next)
//不需要依赖于前驱信息(打印/获取长度)

typedef struct Node
{
	int data;                //数据域
	struct Node *next;       //指针节点(下一个)
}Node,*List;                 //List li;  Node*li;


void InitList(List plist )   //初始化单链表
{
	assert(plist!=NULL);
	plist->next=NULL;
}

static Node *BuyNode(int val) //申请新的结点
{
	Node *p=(Node *)malloc(sizeof(Node));
	assert(p!=NULL);

	p->data=val;
	p->next=NULL;

	return p;
}

void Insert_head(List plist,int val)    //头插法
{
	//Node newnode;
	//newnode.data=val;//局部变量,函数结束时,释放(错误申)
	
	Node *p=BuyNode(val);                                                
	//plist->next=&newnode;//error

	p->next=plist->next;
	plist->next=p;
}

void Insert_tail(List plist,int val)     //尾插法
{
	Node *p;
	for(p=plist;p->next!=NULL;p=p->next)
	{
		;
	}//p->next==NULL

	/*
	for(p=plist->next;p!=NULL;p=p->next)
	{
		;
	}//p==NULL,错误,p=p->plist或许为空
    */
	Node *q=BuyNode(val);
	p->next=q;	//p->next=BuyNode(val);

}


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


bool Delete(List plist,int key)      //删除节点
{
	Node *p=SearchPri(plist,key);
	if(p==NULL)
	{
		return false;
	}
	Node *q=p->next;
	p->next=q->next;
	free(p->next);
	
}

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

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

int Getlength(List plist)      //获取数据节点的长度,不包括头结点
{
	int count=0;
	for(Node *p=plist->next;p!=NULL;p=p->next)
	{
		count++;
	}
	return count;
}

Node *Search(List plist,int key)       //查找节点
{
	//for(Node *p=plist;p->next!=NULL;p=p->next),找尾巴
	assert(plist!=NULL);
	Node *p;
	for(p=plist->next;p!=NULL;p=p->next)
	{
		if(p->data==key)
		{
			//return p;
			break;
		}
	}
    return p;


	/*
	
	p=plist->next;
	while(p!=NULL && (p->data!=key))//方法2
	{
	   p=p->next;
	}
	return p;

	*/
}

void Destory(List plist)//销毁,以防内存泄漏
{
	Node *p;
	while(plist->next!=NULL)
	{
		p=plist->next;
		plist->next=p->next;
		free(p);
	}
}


Node* Reverse(List p)         //逆置
{
    assert(plist!=NULL);
    Node*revhead=NULL;
    Node*prev=NULL;
    Node*p=plist;
    while(p!=NULL)
    {
        Node*pnext=p->next;
        if(pnext==NULL)
        {
            revhead=p;
        }
        p->next=prev;
        prev=p;
        p=pnext;
    }
    return revhead;
}

以上为单链表的基本相关操作。还需继续完善。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值