list 链表函数(小结)

先上函数代码

#include<iostream>
#include<cstdlib>
#include<string>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;

struct node{
	int data; 
	struct node * next;
};
typedef struct node * List;
List head=NULL;
List current=NULL,pre=NULL;
List CreateEmpty(void)
{
	List Ptrl;
	Ptrl=(List)malloc(sizeof(node));
	return Ptrl;
}
int Length(List Ptrl){
	int i=0;
	while(Ptrl->next!=NULL)//算头结点不算尾节点的情况 
	{
		i++;
		Ptrl=Ptrl->next;
	}
	return i;
}
List Find(int i)
{
	List p=head;
	while(i--)//因为头结点为0,所以是--i 
	{
		p=p->next;
	}
	return p;
}
List Insert(int x,int i,List Ptrl)
{
    List p,s;
    if(i==1) 
    {
        s=(List) malloc(sizeof(struct node));
        s->next=head;
        s->data=x;
        return s;//改变的是表头,所以返回不一样的表头x 
    }
    p=Find(i-1);
    if(p==NULL) 
    {
        cout<<"参数错误,无法插入";
        return NULL;
    }
    else
    {
        s=(List) malloc(sizeof(struct node));//s是新节点 p是查找到的需要被插入的节点 
        s->next=p->next;
        p->next=s;
        s->data=x;
        return Ptrl;//因为是在中间插入节点,所以返回时仍是Ptrl没有改变表头 
    }
}
List Delete(int i,List Ptrl)//i是待删除的节点号  Ptrl是传进来的待操作的链表头 
{
	List s,p;
	if(i==1) //头结点的情况 
	{
		s=Ptrl;
		if(Ptrl!=NULL) 
			Ptrl=Ptrl->next;
		else
			return NULL;
		free(s);	
		return Ptrl;
	}
	else//中间节点的情况 
	{
		s=Find(i-1);
		p=s->next;
		s->next=p->next;
		free(p);
		return Ptrl;
	}
}
int main()
{
	while(1)
        {
            current=CreateEmpty();//1开辟 

            cin>>current->data;//2赋值 
            if(current->data==-1) break;

            if(head==NULL) //3链接 
                head=current;
            else
                pre->next=current;

            current->next=NULL;//4初始 

            pre=current;//5存尾 
        }    


	head=Insert(110,3,head);//插入
	head=Delete(3,head);//删除
	current=head;
	while(current!=NULL)
	{
		cout<<current->data<<endl;
		current=current->next;
	}
 } 

函数总结:

一、node是结构体

struct node{
	int data; 
	struct node * next;
};

data是数据域;

二、(重)head头指针一定要在用之前赋空,否则程序会崩溃;

三(过程!!)一个链表的创建:

1、创建表头与操作指针

List head=NULL;
List current=NULL,pre=NULL;

head是表头,也就是表名;

current是操作指针,pre是暂存指针,在链接时与上一链表链接;

2、创建空节点:(创建)

List CreateEmpty(void)
{
	List Ptrl;
	Ptrl=(List)malloc(sizeof(node));
	return Ptrl;
}

调用的时候可以用循环来获取新得到的节点:

current=CreateEmpty();//1创建

3、赋值并判断

            cin>>current->data;//2赋值 
            if(current->data==-1) break;

创建节点后需要直接进行赋值

然后对值进行判断才可知此节点是否可以被链接

这个链表的判断是==-1时跳出,其他链表看情况进行判断

4、链接链表:(链接)

         if(head==NULL) //2链接 
         head=current;
         else
         pre->next=current;

链接的本质是在操作本轮的节点时,将本节点的赋值给pre的next指针,只有头结点是将本节点直接赋给head头指针;

5、初始化next指针:(更尾)

 current->next=NULL;//3更尾 

这个初始化其实就是更新链表表尾,每一轮都将本轮节点的next赋NULL;

6、储存表尾

pre=current;//5存尾

储存本轮表尾,下一轮时用来链接下轮node,操作是将本轮指针赋值给pre即可;

7、结束

while(1)
        {
            ...
            if(current->data==-1) break;//6结束
        }    

在这里用的while(1)+if判断本轮数据域来

四:链表函数

typedef struct node* List;

1、求表长

返回值:int

参数:表头List

int Length(List Ptrl){
	int i=0;
	while(Ptrl->next!=NULL)//算头结点不算尾节点的情况 
	{
		i++;
		Ptrl=Ptrl->next;
	}
	return i;
}

一个循环从表头遍历一遍链表即可,

2、找位置

返回值:List

参数:位置i

List Find(int i)
{
	List p=head;
	while(i--)//因为头结点为0 
	{
		p=p->next;
	}
	return p;
}

(重点!)头结点位置为0!!!

返回值是该位置的List;

3、插入值

参数:插入的值x,插入的位置,需要插入的链表头Ptrl;

返回值:已经插入好的List,用表头接收即可;

List Insert(int x,int i,List Ptrl)
{
    List p,s;
    if(i==1) 
    {
        s=(List) malloc(sizeof(struct node));
        s->next=head;
        s->data=x;
        return s;//改变的是表头,所以返回不一样的表头x 
    }
    p=Find(i-1);
    if(p==NULL) 
    {
        cout<<"参数错误,无法插入";
        return NULL;
    }
    else
    {
        s=(List) malloc(sizeof(struct node));//s是新节点 p是查找到的需要被插入的节点 
        s->next=p->next;
        p->next=s;
        s->data=x;
        return Ptrl;//因为是在中间插入节点,所以返回时仍是Ptrl没有改变表头 
    }
}

s是新节点,p是Find(i-1);

先创建s,再对s和p进行指针操作即可;

传进的参数是第i个,插入的位置是i之后,所以这种写法是后插法,

因为表头是第0个,所以需要Find(i-1);

还有就是

        s->next=p->next;
        p->next=s;

这个顺序是不能改变的

1.先把前节点的next赋给新节点的next

2.新节点赋给前节点的next

4、删除节点

参数:i是传进来的位置 Ptrl是待删除的链表头

返回值:已经删除过的链表头

List Delete(int i,List Ptrl)//i是待删除的节点号  Ptrl是传进来的待操作的链表头 
{
	List s,p;
	if(i==1) //头结点的情况 
	{
		s=Ptrl;
		if(Ptrl!=NULL) 
			Ptrl=Ptrl->next;
		else
			return NULL;
		free(s);	
		return Ptrl;
	}
	else//中间节点的情况 
	{
		s=Find(i-1);
		p=s->next;
		s->next=p->next;
		free(p);
		return Ptrl;
	}
}

前    中    后

s      p      p->next

同样是后删法,同样需要创建s和p节点;

s=Find(i-1)

p有两个作用

一是将p->next赋值给s->next

二是记录被删除的节点,待删除后释放内存;

总结:松松散散的看了也近一个月的链表,不敢说这段时间没有懈怠,恩,走下去罢,一切都会好的

care for self

care for other

猜你喜欢

转载自blog.csdn.net/qq_41660465/article/details/79883029