精华内容
下载资源
问答
  • C语言链表操作详解

    万次阅读 多人点赞 2018-12-29 19:01:55
    为什么要使用链表 在未学习链表时,我们常用的存储数据的方式无非就是数组。...而链表则可以实现以上这些数组所不具备的功能,此时引入了结构体来实现创建链表操作链表的特点: n个节点离散分配 每一个节...

    为什么要使用链表

    在未学习链表时,我们常用的存储数据的方式无非就是数组。使用数组存储数据的好处就是查询快,但是它的弊端也很明显:

    1.  使用前需声明数组的长度,一旦声明长度就不能更改
    2. 插入和删除操作需要移动大量的数组元素,效率慢
    3. 只能存储一种类型的数据.

    而链表则可以实现以上这些数组所不具备的功能,此时引入了结构体来实现创建链表的操作。

    链表的特点:

    1.  n个节点离散分配
    2. 每一个节点之间通过指针相连
    3. 每一个节点有一个前驱节点和一个后继节点
    4. 首节点没有前驱节点,尾节点没有后继节点

    首先先定义一个简单的结构体

    struct link{
           int data;          //定义数据域
           struct link *next; //定义指针域,存储直接后继的节点信息
    };

    数据域的内容可以自己指定,指针域用来存放下一个节点的地址。

    创建链表前须知

    首节点:存放第一个有效数据的节点

    头节点:在单链表的第一个结点之前附设一个结点,它没有直接前驱,称之为头结点,头结点的数据域可以不存储任何信息,指针域指向第一个节点(首节点)的地址。头结点的作用是使所有链表(包括空表)的头指针非空

    头指针:指向头节点的指针

    尾节点:存放最后一个有效数据的节点

    尾指针:指向尾节点的指针

    建立一个单向链表

    方法:定义方法向链表中添加节点来建立一个单向链表

    思路:首先定义一个结构体指针变量p,使用malloc函数为新建节点申请内存空间,让p指向这个节点(指向它刚申请的内存空间),再将其添加到链表中。此时需考虑两种情况:

    1.若单链表为空表,则将新建节点置为头节点

    //若此时只在链表中插入头节点
    struct link *p = head;
    p = (struct link *)malloc(sizeof(struct link));  //让p指向新建节点创建的内存空间
    if(p == NULL){   //新建节点申请内存失败
        exit(0);
    }
    //此时head也指向头节点的地址
    p->next = NULL;     //因为没有后续节点,所以新建节点指针域置空

    2.链表非空,则将新建节点添加到表尾

    //此时已存在头节点,再插入一个节点(首节点)
    struct link *p = NULL,*pr = head;  
    p = (struct link *)malloc(sizeof(struct link));
    if(p == NULL){
        exit(0);
    }
    if(head == NULL){
        head = p;
    }else{
        while(pr->next != NULL){     //当头节点的指针域不为NULL
          pr = pr->next;             //pr指向下一个节点的地址
      }
        pr->next = p;                //使头节点的指针域存储下一个节点的地址
    }

    完整操作

    #include <stdio.h>
    #include <stdlib.h>
    struct link *AppendNode(struct link *head);
    void DisplayNode(struct link *head);
    void DeleteMemory(struct link *head);
    //定义结构体 
    struct link{
    	int data; 				//定义数据域 
    	struct link *next; 			//定义指针域 
    }; 
    int main(){
    	int i =0;         			//定义i,记录创建的节点数 
    	char c;							
    	struct link *head = NULL;		//创建头指针,初始化为NULL 
    	printf("DO you wang to append a new node(Y or N)?");
    	scanf(" %c",&c);				
    	while(c == 'Y' || c == 'y'){	//如果确定继续添加结点 
    		head = AppendNode(head);	//通过函数获得链表的地址,AppendNode函数返回的是链表的头指针
    		                            //可以根据头指针指向的地址来获取链表中保存的数据 
    		DisplayNode(head);			//根据头指针打印链表 
    		printf("DO you want to append a new node(Y or N)?");
    		scanf(" %c",&c);
    		i++; 
    	}
    	printf("%d new nodes hava been appended!\n",i);
    	DeleteMemory(head);			//释放占用的内存 
    }
    struct link *AppendNode(struct link *head){    //声明创建节点函数 
    	struct link *p = NULL,*pr = head;      //创建p指针,初始化为NULL;创建pr指针,通过pr指针来给指针域赋值 
    	int data ;
    	p = (struct link *)malloc(sizeof(struct link)) ; //为指针p申请内存空间,必须操作,因为p是新创建的节点 
    	if(p == NULL){			//如果申请内存失败,则退出程序 
    		printf("NO enough momery to allocate!\n");
    		exit(0);
    	}
    	if(head == NULL){		//如果头指针为NULL,说明现在链表是空表 
    		head = p;								//使head指针指向p的地址(p已经通过malloc申请了内存,所以有地址) 
    	}else{										//此时链表已经有头节点 ,再一次执行了AppendNode函数 
    												//注:假如这是第二次添加节点
    	                                  //因为第一次添加头节点时,pr = head,和头指针一样指向头节点的地址 
    		while(pr->next!= NULL){		//当pr指向的地址,即此时的p的指针域不为NULL(即p不是尾节点) 
    			pr = pr->next;	//使pr指向头节点的指针域
    		}
    		pr->next = p;	//使pr的指针域指向新键节点的地址,此时的next指针域是头节点的指针域 
    	}
    	printf("Input node data:");                   
    	scanf("%d",&data);
    	p->data = data; 			//给p的数据域赋值 
    	p->next = NULL;			//新添加的节点位于表尾,所以它的指针域为NULL 
    	return head;			//返回head的地址 
    }
    void DisplayNode(struct link *head){         	//输出函数,打印链表 
    	struct link *p = head;			// 定义p指针使其指向头节点 
    	int j = 1;									//定义j记录这是第几个数值 
    	while(p != NULL){		//因为p = p->next,所以直到尾节点打印结束 
    		printf("%5d%10d\n",j,p->data);			
    		p = p->next;		//因为节点已经创建成功,所以p的指向由头节点指向下一个节点(每一个节点的指针域都指向了下一个节点) 
    		j++;	
    	}
    }
    void DeleteMemory(struct link *head){			//释放资源函数 
    	struct link *p = head,*pr = NULL;	        //定义p指针指向头节点 
    	while(p != NULL){				//当p的指针域不为NULL 
    		pr = p;									//将每一个节点的地址赋值给pr指针 
    		p = p->next;			        //使p指向下一个节点 
    		free(pr);								//释放此时pr指向节点的内存 
    	}
    }

    第二种创建链表方式-优化

    #include <stdio.h> 
    #include <stdlib.h>
    struct Stu *create(int n);
    void print(struct Stu *head);
    struct Stu{
    	int id;
    	char name[50];
    	struct Stu *next;
    };
    int main(){
    	int n;
    	struct Stu *head = NULL;   //创建头指针 
    	printf("请输入你想要创建的节点个数:\n");
    	scanf("%d",&n);
    	head = create(n);
    	print(head);
    }
    struct Stu *create(int n){
    	struct Stu *head,*node,*end;   						//定义头节点,普通节点,尾节点 
    	head = (struct Stu *)malloc(sizeof(struct Stu)); 	//给头节点申请内存 
    	end = head;        									//若是空表,则头尾地址一致 
    	for(int i=0;i<n;i++){								//利用for循环向链表中添加数据 
    		node = (struct Stu *)malloc(sizeof(struct Stu));//给普通节点申请内存空间 
    		scanf("%d %s",&node->id,node->name);	//给数据域赋值 
    		end->next = node;					//让上一个节点的数据域指向当前节点 
    		end = node;     						//end指向当前节点,最终end指向尾节点 
    	}
    	end->next = NULL;                                   //给end的指针域置空 
    	return head;                                        //返回头节点的地址 
    }
    void print(struct Stu *head){
    	struct Stu *p = head;
    	int j =1;
    	p = p->next;  //不打印头节点的数据域中的值 
    	while(p != NULL){
    		printf("%d\t%d\t%s\n",j,p->id,p->name);
    		p = p->next;
    		j++;
    	}
    }

    前插法创建链表 --逆序输出

    struct link *create(int n){
         struct link *headnode ,*node;
         headnode = (struct link *)malloc(sizeof(struct link));   //为头节点申请内存 
    	 headnode ->next = NULL;     //让头节点的指针域置空 
    	 for(int i=0;i<n;i++){ 
    	 	node = (struct link *)malloc(sizeof(struct link));  //给新建节点申请内存 
    	 	scanf("%d",&node->data);       //新建节点数据域传值 
    	 	node->next = headnode->next;   //新建节点的数据域指向头节点 == 创建尾节点 
    	 	headnode->next = node;         //将新建节点数据域传给头节点 
    	 }	
    	 return headnode;  
    }

     

    删除节点

    void deleteNode(struct Stu *head,int n){         //删除n处的节点 
    	struct  Stu *p = head,*pr = head;
    	int i =0;
    	while(i<n&&p!=NULL){       //到达指定节点,此时p指向指定节点,pr指向上一节点 
    		pr = p;            //将p的地址赋值给pr
    		p = p->next;       //p指向下一节点
    		i++;
    	}
    	if(p!=NULL){               //当p不为空时,即p不能指向尾节点之后的节点
    		pr->next = p->next;
    		free(p);
    	} else{
    		printf("节点不存在!\n"); 
    	}
    } 

    我在这着重解释一下p->next = NULL和p!=NULL的区别,因为我刚开始也经常弄错!!

    • while(p->next != NULL) 循环结束时,此时p的位置是尾节点的位置,但如果用于输出函数的判断条件,则尾节点的数据不会输出。
    • while(p!=NULL) 循环结束时, 此时p指向的位置为尾节点的下一个节点,因为没有申请内存空间,所以是一个未知的区域。

    插入节点

    void insertNode(struct Stu *head,int n){    //插入节点 
    	struct Stu *p = head,*pr;
    	pr = (struct Stu*)malloc(sizeof(struct Stu));  //让pr指向新建节点申请的内存 
    	printf("input data:\n");
    	scanf("%d %s",&pr->id,pr->name);
    	int i = 0;
        //当插入位置是尾节点时,只要在尾节点后再插入一个节点,并让尾节点的指针域指向新建节点,新建节点的指针域置空
        while(i<n&&p!=NULL){             //使p指向将要插入节点的位置 
        	p = p->next;
    		i++;
    	}
    	if(p!=NULL){            //如果p没越界 
    		pr->next = p->next; //将新建节点的地址指向将要插入节点的后一个节点的地址 
    		p->next = pr;       //使插入节点指向新建节点 
    	}else{
    		printf("节点不存在!\n");
    	}
    }

    修改节点

    void change(struct Stu *head,int n){
    	struct Stu *p = head;
    	int i = 0;
    	while(i<n && p!=NULL){      //使p指向需修改节点 
    		p = p->next;
    		i++;
    	}
    	if(p != NULL){             
    	printf("请输入修改之后的值:\n");
    	scanf("%d %s",&p->id,p->name);	
    	}else{
    		printf("节点不存在!\n");
    	} 

    链表的逆序

     

    思路:假如此时链表有两个有效节点,头节点为0号,中间的节点为1号,尾节点为2号

    1.定义三个指针pf指向链表的头节点(0号),tmp,pb初始化为NULL

    2.让pb指向pf的下一个节点(1号),并将此时头节点的指针域置空(变为尾节点)

    3.第一次while循环,让tmp指向pb(1号),然后让pb指向下一个节点,再让tmp让1号节点的指针域(tmp->next = pf)指向pf(上一个节点)(0号),再将pf指向tmp(1号)(pf = tmp)

    4.第二次while循环,让tmp指向pb(2号),然后让pb指向下一个节点,此时pb==NULL,所以这是最后一次循环,再让tmp让2号节点的指针域(tmp->next = pf)指向pf(1号),再将pf指向tmp(2号)

     5.此时链表逆序完成,让头指针指向首节点(2号),返回头指针即可

                                                                              逆序后

    STU *link_reversed_order(STU *head)
    {
        STU *pf = NULL, *pb = NULL, *tmp = NULL; 
        pf = head;  //将头节点的地址赋值给pf 
        if(head == NULL) { //如果链表为空 
            printf("链表为空,不需要逆序!\n");
            return head;
        } else if(head->next == NULL) {  //如果只有一个节点 
            printf("链表只有一个节点,不需要逆序!\n");
            return head;
        } else {
            pb = pf->next;  //pb指向pf的下一个节点 
            head->next = NULL; //头节点的指针域置空(变为尾节点) 
            while(pb != NULL)	//当pb不为空时 
            {
                tmp = pb;	//将pb的地址赋值给temp 
                pb = pb->next; //pb指向下一个节点 
                tmp->next = pf;	//pb的上一个节点的指针域指向pf 
                pf = tmp;	//让pf指向tmp 
            }
            head = pf;
            return head;
        }    
    }*/

    所有操作

    #include <stdio.h> 
    #include <stdlib.h>
    struct Stu *create(int n);
    void print(struct Stu *head);
    void deleteNode(struct Stu *head,int n);
    void insertNode(struct Stu *head,int n);
    void change(struct Stu *head,int n);
    struct Stu{
    	int id;
    	char name[50];
    	struct Stu *next;
    };
    int main(){
    	int n,j,in,cn;
    	char c;
    	struct Stu *head = NULL;   //创建头指针 
    	printf("请输入你想要创建的节点个数:\n");
    	scanf("%d",&n);
    	head = create(n);
    	print(head);
    	while(true){
    	printf("请选择你想要执行的操作:\n");
    	printf("1.插入节点\n2.删除节点\n3.修改节点\n4.退出程序\n");
    	scanf(" %c",&c);
    	if(c =='1'){
    	printf("你想要在哪插入节点:\n");
    	scanf("%d",&in);
    	insertNode(head,in);
    	print(head); 
    	}else if(c == '2'){
    	printf("你想要删除哪个节点的数据:\n");
    	scanf("%d",&j);
    	deleteNode(head,j);
    	print(head);
    	}else if(c =='3'){
    	printf("你想要修改哪个节点的数据:\n");
    	scanf("%d",&cn);
    	change(head,cn);
    	print(head); 
    	}else if(c =='4'){
    		exit(0);
    	} 		
     } 
    }
    struct Stu *create(int n){
    	struct Stu *head,*node,*end;   						//定义头节点,普通节点,尾节点 
    	head = (struct Stu *)malloc(sizeof(struct Stu)); 	//给头节点申请内存 
    	//head->id = n;										//头节点的数据域保存链表的长度 
    	end = head;        									//若是空表,则头尾地址一致 
    	for(int i=0;i<n;i++){								//利用for循环向链表中添加数据 
    		node = (struct Stu *)malloc(sizeof(struct Stu));//给普通节点申请内存空间 
    		scanf("%d %s",&node->id,node->name);			//给数据域赋值 
    		end->next = node;								//让上一个节点的数据域指向当前节点 
    		end = node;     								//end指向当前节点,最终end指向尾节点 
    	}
    	end->next = NULL;                                   //给end的指针域置空 
    	return head;                                        //返回头节点的地址 
    }
    void print(struct Stu *head){
    	struct Stu *p = head;
    	int j =1;
    	p = p->next;  //不打印头节点的数据域中的值 
    	while(p != NULL){
    		printf("%d\t%d\t%s\n",j,p->id,p->name);
    		p = p->next;
    		j++;
    	}
    }
    void deleteNode(struct Stu *head,int n){         //删除n处的节点 
    	struct  Stu *p = head,*pr = head;
    	int i =0;
    	while(i<n&&p!=NULL){       //到达指定节点,此时p指向指定节点,pr指向上一节点 
    		pr = p;
    		p = p->next;
    		i++;
    	}
    	if(p!=NULL){
    		pr->next = p->next;
    		free(p);
    	} else{
    		printf("节点不存在!\n"); 
    	}
    } 
    void insertNode(struct Stu *head,int n){    //插入节点 
    	struct Stu *p = head,*pr;
    	pr = (struct Stu*)malloc(sizeof(struct Stu));  //让pr指向新建节点申请的内存 
    	printf("input data:\n");
    	scanf("%d %s",&pr->id,pr->name);
    	int i = 0;
        //当插入位置是尾节点时,只要在尾节点后再插入一个节点,并让尾节点的指针域指向新建节点,新建节点的指针域置空
        while(i<n&&p!=NULL){             //使p指向将要插入节点的位置 
        	p = p->next;
    		i++;
    	}
    	if(p!=NULL){            //如果p没越界 
    		pr->next = p->next; //将新建节点的地址指向将要插入节点的后一个节点的地址 
    		p->next = pr;       //使插入节点指向新建节点 
    	}else{
    		printf("节点不存在!\n");
    	}
    }
    void change(struct Stu *head,int n){
    	struct Stu *p = head;
    	int i = 0;
    	while(i<n && p!=NULL){      //使p指向需修改节点 
    		p = p->next;
    		i++;
    	}
    	if(p != NULL){             
    	printf("请输入修改之后的值:\n");
    	scanf("%d %s",&p->id,p->name);	
    	}else{
    		printf("节点不存在!\n");
    	} 	 
    } 

     

     

    展开全文
  • 链表操作总结

    千次阅读 2018-04-03 21:28:36
    链表操作总结(创建,遍历,就地逆置,删除偶数结点…) 1、随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。 2、遍历单向链表(显示)。 3、把单向链表中元素逆置(不允许申请新的结点空间)。 ...

    链表操作总结(创建,遍历,就地逆置,删除偶数结点…)

    1、随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
    2、遍历单向链表(显示)。
    3、把单向链表中元素逆置(不允许申请新的结点空间)。
    4、在单向链表中删除所有的偶数元素(值为偶数)结点。
    5、编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单向链表。
    6、利用算法5建立两个非递减有序单向链表,然后合并成一个非递增链表。
    7、利用算法5建立两个非递减有序单向链表,然后合并成一个非递减链表。
    8、编写一个主函数,调试上述算法。
    所用函数::
    1.创建带头节点的单向链表,输入一组元素
    2.显示单向链表
    3.逆置元素(不申请新节点)
    4.删除所有值为偶数的节点
    5.递增数列中插入元素仍有序
    6.建立两个递增的有序单向链表,合并成一个递增
    7.建立两个递减的有序单向链表,合并成一个递减

    //
    //  main.cpp
    //  Listlist
    //
    //  Created by 王子谖on 2018/4/2.
    //  Copyright © 2018 王子谖. All rights reserved.
    //
    /```
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    using namespace std;
    
    /*
     实验内容:
     1、随机产生或键盘输入一组元素,建立一个带头结点的单向链表(无序)。
     2、遍历单向链表(显示)。
     3、把单向链表中元素逆置(不允许申请新的结点空间)。
     4、在单向链表中删除所有的偶数元素(值为偶数)结点。
     5、编写在非递减有序链表中插入一个元素使链表元素仍有序的函数,并利用该函数建立一个非递减有序单向链表。
     6、利用算法5建立两个非递减有序单向链表,然后合并成一个非递增链表。
     7、利用算法5建立两个非递减有序单向链表,然后合并成一个非递减链表。
     8、编写一个主函数,调试上述算法。
    所用函数::
     1.创建带头节点的单向链表,输入一组元素
     2.显示单向链表
     3.逆置元素(不申请新节点)
     4.删除所有值为偶数的节点
     5.递增数列中插入元素仍有序
     6.建立两个递增的有序单向链表,合并成一个递减
     7.建立两个递减的有序单向链表,合并成一个递增
     */
    
    
    typedef struct node
    {
        int data;
        struct node *next;
    }LNode,*LinkList;
    
    //1.创建带头节点的单向链表
    void init(LinkList &L)
    {
        L=(LinkList)malloc(sizeof(LNode));
        L->next=NULL;
    }
    //1.输入一组数,头插法
    void insert1(LinkList &L,int m)
    {
        LinkList p;
        p=(LinkList)malloc(sizeof(LNode));
        p->data=m;
        p->next=L->next;
        L->next=p;
    }
    //1.输入一组数,尾插法
    void insert2(LinkList &L,int m)
    {
        LinkList p,q;
        p=(LinkList)malloc(sizeof(LNode));
        p->data=m;
        p->next=NULL;
        q=L;
        if(L==NULL) //首节点为空
        {   L=p;  //L指向p
            p->next=NULL;
        }
        else{
            while (q->next!=NULL)
            {
                q=q->next;//到尾巴时
            }
            q->next=p; //插入结点
        }
    
    }
    //2.显示单向链表
    void print(LinkList &L)
    {
        LinkList p;
        p=(LinkList)malloc(sizeof(LNode));
        p=L->next;
        while(p)
        {   printf("%d ",p->data);
            p=p->next;
        }
        printf("\n");
    }
    //3.逆置元素(不申请新节点)
    void contrary(LinkList &L){
        LinkList p,q;
        p=(LinkList)malloc(sizeof(LNode));
        q=(LinkList)malloc(sizeof(LNode));
        p=L->next;
        L->next=NULL;//将链断开
        while (p) {
            q=p->next;//q永远在p的后一个
            p->next=L->next;//将p连在L的后面,先把尾巴连上
            L->next=p;//将p连在L的后面,再把前面接上
            p=q;//p指向下一个,即q所在的位置
        }
    }
    //4.删除所有值为偶数的节点
    void delet(LinkList &L)
    {
        LinkList p,q;
        p=(LinkList)malloc(sizeof(LNode));
        q=(LinkList)malloc(sizeof(LNode));
        p=L->next;
        q=L;
        while(p)
        {
               if((p->data)%2!=0)
                {
                     p=p->next;
                     q=q->next;
                }
               else{
                   q->next=p->next;//删除节点
                   p=p->next;
               }
        }
    }
    //5.递增数列中插入元素仍有序
    void insert3(LinkList &L,int c)
    {
        LinkList p,q,s;
        s=(LinkList)malloc(sizeof(LNode));
        p=(LinkList)malloc(sizeof(LNode));
        q=(LinkList)malloc(sizeof(LNode));
        p=L->next;
        q=L;
        s->data=c;
        while((p->data<=c)&&(p->next!=NULL))//条件是p->next!=null
        {   p=p->next;
            q=q->next;
        }
        if(p->next==NULL)//特殊考虑p指向结尾
        {
            p->next=s;
            s->next=NULL;
        }
        else{
            s->next=p;
            q->next=s;
        }
    
    }
    //6.建立两个递增的有序单向链表,合并成一个递减(建立两个递增的有序单向链表,合并成一个递增,再就地逆置元素)
    LinkList inde(LinkList &L,LinkList &J)
    {
    
        LinkList Q;
        init(Q);
        LinkList pa,pb,pc;
        pa=(LinkList)malloc(sizeof(LNode));
        pb=(LinkList)malloc(sizeof(LNode));
        pc=(LinkList)malloc(sizeof(LNode));
        pa=L->next;
        pb=J->next;
        pc=Q;
        pc->next=NULL;
        while(pa&&pb)
        {
            if(pa->data<=pb->data)
            {
                pc->next=pa;
                pc=pa;
                pa=pa->next;
            }
            else {
                pc->next=pb;
                pc=pb;
                pb=pb->next;
            }
        }
        if(pa)
        {
            pc->next=pa;
        }
        else
        {
            pc->next=pb;
        }
        free(L);
        free(J);
    
        return Q;
    }
    //7.建立两个递减的有序单向链表,合并成一个递增(建立两个递减的有序单向链表,合并成一个递减,再就地逆置元素)
    LinkList dein(LinkList &L,LinkList &J)
    {
    
        LinkList Q;
        init(Q);
        LinkList pa,pb,pc;
        pa=(LinkList)malloc(sizeof(LNode));
        pb=(LinkList)malloc(sizeof(LNode));
        pc=(LinkList)malloc(sizeof(LNode));
        pa=L->next;
        pb=J->next;
        pc=Q;
        pc->next=NULL;
        while(pa&&pb)
        {
            if(pa->data>=pb->data)
            {
                pc->next=pa;
                pc=pa;
                pa=pa->next;
            }
            else {
                pc->next=pb;
                pc=pb;
                pb=pb->next;
            }
        }
        if(pa)
        {
            pc->next=pa;
        }
        else
        {
            pc->next=pb;
        }
        free(L);
        free(J);
    
        return Q;
    }
    
    
    
    
    int main()
    {
        LinkList S;
    int number,data;
        init(S);//创建带头节点的链表
        printf("创建带头节点的链表\n");
        printf("输入插入元素的个数\n");
        scanf("%d",&number);//输入插入元素的个数
        for(int i=0;i<number;i++)
        {
            printf("尾插法,依次输入元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(S,data);//1.头插法,输入元素
            insert2(S,data);//1.尾插法,输入元素
        }
        printf("\n显示带头节点的链表\n");
        print(S);// 2.显示单向链表
        printf("显示逆置的链表\n");
        contrary(S);//3.逆置元素(不申请新节点)
        print(S);// 2.显示单向链表
        printf("删除所有值为偶数的节点\n");
        delet(S); // 4.删除所有值为偶数的节点
        print(S);// 2.显示单向链表
    
        LinkList U;
        init(U);//创建带头节点的链表
        printf("输入插入元素的个数\n");
        scanf("%d",&number);//输入插入元素的个数
        for(int i=0;i<number;i++)
        {
            printf("尾插法,依次输入有序递增元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(U,data);//1.头插法,输入元素
            insert2(U,data);//1.尾插法,输入元素
        }
        printf("输入要插入的元素\n");
        int k;
        scanf("%d",&k);//要插入递增数列的k
        insert3(U,k);//5.递增数列中插入元素仍有序
        print(U);// 2.显示单向链表
    
    
        LinkList V,W,Res;
        int m,n;
        init(V);//创建带头节点的链表
        init(W);//创建带头节点的链表
        printf("输入两个链表的元素个数分别为m,n\n");
        scanf("%d%d",&m,&n);//输入插入元素的个数
        printf("请输入第一个链表的元素\n");
        for(int i=0;i<m;i++)
        {
            printf("尾插法,依次输入有序递增元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(U,data);//1.头插法,输入元素
            insert2(V,data);//1.尾插法,输入元素
        }
        printf("请输入第二个链表的元素\n");
        for(int i=0;i<n;i++)
        {
            printf("尾插法,依次输入有序递增元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(U,data);//1.头插法,输入元素
            insert2(W,data);//1.尾插法,输入元素
        }
            Res=inde(V,W);//6.建立两个递增的有序单向链表,合并成一个递减
            contrary(Res);//3.逆置元素(不申请新节点)
            print(Res);// 2.显示单向链表
    
        LinkList E,F,Re;
        int a,b;
        init(E);//创建带头节点的链表
        init(F);//创建带头节点的链表
        printf("输入两个链表的元素个数分别为m,n\n");
        scanf("%d%d",&a,&b);//输入插入元素的个数
        printf("请输入第一个链表的元素\n");
        for(int i=0;i<a;i++)
        {
            printf("尾插法,依次输入有序递减元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(U,data);//1.头插法,输入元素
            insert2(E,data);//1.尾插法,输入元素
        }
        printf("请输入第二个链表的元素\n");
        for(int i=0;i<b;i++)
        {
            printf("尾插法,依次输入有序递减元素,以回车分隔,输入元素第%d个\n",i+1);
            scanf("%d",&data);
            //insert1(U,data);//1.头插法,输入元素
            insert2(F,data);//1.尾插法,输入元素
        }
        Re=dein(E,F);//7.建立两个递减的有序单向链表,合并成一个递增
        contrary(Re);//3.逆置元素(不申请新节点)
        print(Re);// 2.显示单向链表
    
    
    
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载

    展开全文
  • Js实现链表操作

    千次阅读 2020-05-13 11:57:27
    Js实现链表操作 JavaScript实现链表主要操作,包括创建链表、遍历链表、获取链表长度、获取第i个元素值、获取倒数第i个元素值、插入节点、删除节点、有序链表合并、有序链表交集。 创建链表 class Node{ ...

    Js实现链表操作

    JavaScript实现链表主要操作,包括创建链表、遍历链表、获取链表长度、获取第i个元素值、获取倒数第i个元素值、插入节点、删除节点、有序链表合并、有序链表交集。

    创建链表

    class Node{
        constructor(data){
            this.data = data;
            this.next = null;
        }
    }
    
    function createLinkList(arr){
        var L = new Node(null);
        var p = L;
        arr.forEach(v => {
            p.next = new Node(v);
            p=p.next;
        })
        return L;
    }
    
    (function(){
        var arr = [1, 3, 5, 7, 9]; // 为了方便,将数组转化为链表
        var L = createLinkList(arr);
    })
    

    遍历链表

    function traverseLinkList(L){
        var p = L.next;
        while(p){
            console.log(p.data);
            p = p.next;
        }
    }
    

    获取链表长度

    function getLinkListLength(L){
        var p = L.next;
        var n = 0;
        while(p) {
            ++n;
            p = p.next;
        };
        return n;
    }
    

    获取第i个元素值

    function getIndexValue(L, index){
        var p = L.next;
        if(index <=0 ) return null;
        var n = 0;
        while(p) {
            ++n;
            if(index === n) return p.data;
            p = p.next;
        };
        return null;
    }
    

    获取倒数第i个元素值

    function getReverseIndexValue(L, index){
        var p = L.next;
        if(index <=0 ) return null;
        var cursor = L;
        var n = 0;
        while(p) {
            ++n;
            if(n >= index) cursor = cursor.next;
            p = p.next;
        };
        if(n < index) return null;
        return cursor.data;
    }
    

    插入节点

    function insertNode(L, posistion, value){
        var p = L.next;
        var i = 0;
        while(p){
            ++i;
            if(i === posistion) {
                var saveNextP = p.next;
                p.next = new Node(value);
                p.next.next = saveNextP;
                return true;
            }
            p = p.next;
        }
        return false;
    }
    

    删除节点

    function deleteNode(L, posistion){
        var p = L.next;
        var preNode = L;
        var i = 0;
        while(p){
            ++i;
            if(i === posistion) {
                preNode.next = p.next;
                p = null;
                return true;
            }
            preNode = preNode.next;
            p = p.next;
        }
        return false;
    }
    

    有序链表合并

    function mergeLinkList(L1, L2){
        var p1 = L1.next;
        var p2 = L2.next;
        var L3 = new Node(null);
        var p3 = L3;
        while(p1 && p2){
            if(p1.data < p2.data){
                p3.next = new Node(p1.data);
                p3 = p3.next;
                p1 = p1.next;
            }else{
                p3.next = new Node(p2.data);
                p3 = p3.next;
                p2 = p2.next;
            }
        }
        while(p1) {
            p3.next = new Node(p1.data);
            p3 = p3.next;
            p1 = p1.next;
        }
        while(p2){
            p3.next = new Node(p2.data);
            p3 = p3.next;
            p2 = p2.next;
        }
        return L3;
    }
    

    有序链表交集

    function unionLinkList(L1, L2){
        var p1 = L1.next;
        var p2 = L2.next;
        var L3 = new Node(null);
        var p3 = L3;
        while(p1 && p2){
            if(p1.data === p2.data){
                p3.next = new Node(p1.data);
                p3 = p3.next;
                p1 = p1.next;
                p2 = p2.next;
            }else if(p1.data < p2.data){
                p1 = p1.next;
            }else{
                p2 = p2.next;
            }
        }
        p3.next = null;
        return L3;
    }
    

    示例

    class Node{
        constructor(data){
            this.data = data;
            this.next = null;
        }
    }
    
    
    function createLinkList(arr){
        var L = new Node(null);
        var p = L;
        arr.forEach(v => {
            p.next = new Node(v);
            p=p.next;
        })
        return L;
    }
    
    function traverseLinkList(L){
        var p = L.next;
        while(p){
            console.log(p.data);
            p = p.next;
        }
    }
    
    function getLinkListLength(L){
        var p = L.next;
        var n = 0;
        while(p) {
            ++n;
            p = p.next;
        };
        return n;
    }
    
    function getIndexValue(L, index){
        var p = L.next;
        if(index <=0 ) return null;
        var n = 0;
        while(p) {
            ++n;
            if(index === n) return p.data;
            p = p.next;
        };
        return null;
    }
    
    function getReverseIndexValue(L, index){
        var p = L.next;
        if(index <=0 ) return null;
        var cursor = L;
        var n = 0;
        while(p) {
            ++n;
            if(n >= index) cursor = cursor.next;
            p = p.next;
        };
        if(n < index) return null;
        return cursor.data;
    }
    
    function insertNode(L, posistion, value){
        var p = L.next;
        var i = 0;
        while(p){
            ++i;
            if(i === posistion) {
                var saveNextP = p.next;
                p.next = new Node(value);
                p.next.next = saveNextP;
                return true;
            }
            p = p.next;
        }
        return false;
    }
    
    function deleteNode(L, posistion){
        var p = L.next;
        var preNode = L;
        var i = 0;
        while(p){
            ++i;
            if(i === posistion) {
                preNode.next = p.next;
                p = null;
                return true;
            }
            preNode = preNode.next;
            p = p.next;
        }
        return false;
    }
    
    function mergeLinkList(L1, L2){
        var p1 = L1.next;
        var p2 = L2.next;
        var L3 = new Node(null);
        var p3 = L3;
        while(p1 && p2){
            if(p1.data < p2.data){
                p3.next = new Node(p1.data);
                p3 = p3.next;
                p1 = p1.next;
            }else{
                p3.next = new Node(p2.data);
                p3 = p3.next;
                p2 = p2.next;
            }
        }
        while(p1) {
            p3.next = new Node(p1.data);
            p3 = p3.next;
            p1 = p1.next;
        }
        while(p2){
            p3.next = new Node(p2.data);
            p3 = p3.next;
            p2 = p2.next;
        }
        return L3;
    }
    
    function unionLinkList(L1, L2){
        var p1 = L1.next;
        var p2 = L2.next;
        var L3 = new Node(null);
        var p3 = L3;
        while(p1 && p2){
            if(p1.data === p2.data){
                p3.next = new Node(p1.data);
                p3 = p3.next;
                p1 = p1.next;
                p2 = p2.next;
            }else if(p1.data < p2.data){
                p1 = p1.next;
            }else{
                p2 = p2.next;
            }
        }
        p3.next = null;
        return L3;
    }
    
    (function(){
        var arr = [1, 3, 5, 7, 9]; // 为了方便,将数组转化为链表
        console.log("创建链表");
        var L = createLinkList(arr);
        console.log(L);
        console.log("遍历链表");
        traverseLinkList(L);
        console.log("获取链表长度");
        var n = getLinkListLength(L);
        console.log(n);
        console.log("获取链表第2个元素值");
        var v = getIndexValue(L, 2);
        console.log(v);
        console.log("获取链表倒数第2个元素值");
        var v = getReverseIndexValue(L, 2);
        console.log(v);
        console.log("在第1个节点后插入值为2的节点");
        insertNode(L, 1, 2);
        traverseLinkList(L);
        console.log("删除第2个节点");
        deleteNode(L, 2);
        traverseLinkList(L);
        console.log("创建两个有序链表");
        console.log("L1");
        var L1 = createLinkList([1, 5, 7, 10, 30]);
        traverseLinkList(L1);
        console.log("L2");
        var L2 = createLinkList([1, 3, 7, 9, 20, 100]);
        traverseLinkList(L2);
        console.log("合并有序链表,不改变原链表,返回一个新链表");
        var L3 = mergeLinkList(L1, L2);
        traverseLinkList(L3);
        console.log("取有序链表交集,不改变原链表,返回一个新链表");
        var L3 = unionLinkList(L1, L2);
        traverseLinkList(L3);
    })();
    

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    
    展开全文
  • Linux链表操作

    千次阅读 2016-08-23 23:08:54
    在研究linux内核自带的dmatest.c驱动程序过程中发现有部分的链接操作... 普通的链表操作,通常包含数据域和指针域2个内容 如下所示。 typedef struct node {  ElemType data; //数据域   struct node

           在研究linux内核自带的dmatest.c驱动程序过程中发现有部分的链接操作,非常迷惑,故在此记录下来一些查阅资料后的心得体会。

    0 内核链表的特点

           普通的链表操作,通常包含数据域和指针域2个内容 如下所示。

    typedef struct node

    {

         ElemType data;       //数据域

         struct node *next;  //指针域

    }node, *list;

           

    而Linux内核定义的链表不带数据域,只需要两个指针完成链表的操作。具有非常高的扩展性、通用性。链表结构定义如下所示。

    struct list_head {

        struct list_head *next, *prev;

    };

           通常有如下格式的定义,通常建议结合containner_ofoffset_of获取更大的灵活可操作性。例如下例,可以根据app_info_head的地址找出app_info的起始地址,即一个完整的app_info结构的起始地址。

    typedef struct application_info

    {

        uint32_t  app_id;

        uint32_t  up_flow;

        uint32_t  down_flow;

        struct    list_head app_info_head;  //链表节点

    }app_info;

    1 链表操作及实现原理

    (1)   初始化链表头结点

    初始化的效果是使得前驱和后继指针都是指向头结点的。

    这里需要十分注意Init的接口(一开始没有注意到导致错误理解了代码)LIST_HEAD_INIT、LIST_HEAD、INIT_LIST_HEAD三者的区别。

    #define LIST_HEAD_INIT(name) { &(name), &(name) }

    #define LIST_HEAD(name) \

        struct list_head name = LIST_HEAD_INIT(name)

    static inline void INIT_LIST_HEAD(struct list_head *list)

    {

        list->next = list;

        list->prev = list;

    }

    所以有如下两种用法。一种是宏扩展,另一种是函数调用。

    //方式一

    static struct info_t{

        struct list_head channels;

    }info = {

        .channels = LIST_HEAD_INIT(info.channels);

    }

    //方式二

    INIT_LIST_HEAD(&info.channels);

    (2)   插入操作

    list_add和list_add_tail分别是插在表头和表尾,但是都是通过__list_add实现,因为内核实现的链表是双向链表,所以head->prev之后就是表尾,而head->next之后就是表头。内核实现如下表所示。

    static inline void __list_add(struct list_head *new,

                      struct list_head *prev,

                      struct list_head *next)

    {

        next->prev = new;

        new->next = next;

        new->prev = prev;

        prev->next = new;

    }

     

    static inline void list_add(struct list_head *new, struct list_head *head)

    {

        __list_add(new, head, head->next);

    }

     

    static inline void list_add_tail(struct list_head *new, struct list_head *head)

    {

        __list_add(new, head->prev, head);

    }

    (3)   删除操作

    list_del,即删除该节点的前驱和后继节点。需要注意,删除后还需要将待删除节点的前驱和后继分别指向POSITION1和POSITION2。对POSITION1和POSITION2的操作都将引起页故障。

    static inline void __list_del(struct list_head * prev, struct list_head * next)

    {

        next->prev = prev;

        prev->next = next;

    }

     

    static inline void list_del(struct list_head *entry)

    {

        __list_del(entry->prev, entry->next);

        entry->next = LIST_POISON1;

        entry->prev = LIST_POISON2;

    }

    /*

     * These are non-NULL pointers that will result in page faults

     * under normal circumstances, used to verify that nobody uses

     * non-initialized list entries.

     */

    #define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)

    #define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)

    (4)   判断链表

    是否为空(list_empty)是否是最后一结点(list_is_last)。

    /**

     * list_is_last - tests whether @list is the last entry in list @head

     * @list: the entry to test

     * @head: the head of the list

     */

    static inline int list_is_last(const struct list_head *list,

                    const struct list_head *head)

    {

        return list->next == head;

    }

     

    /**

     * list_empty - tests whether a list is empty

     * @head: the list to test.

     */

    static inline int list_empty(const struct list_head *head)

    {

        return head->next == head;

    }

    (5)   遍历链表

    注意list_for_each只是个宏替代。

    /**

     * list_entry - get the struct for this entry

     * @ptr:    the &struct list_head pointer.

     * @type:    the type of the struct this is embedded in.

     * @member:    the name of the list_struct within the struct.

     */

    #define list_entry(ptr, type, member) \

        container_of(ptr, type, member)

     

    /**

     * list_first_entry - get the first element from a list

     * @ptr:    the list head to take the element from.

     * @type:    the type of the struct this is embedded in.

     * @member:    the name of the list_struct within the struct.

     *

     * Note, that list is expected to be not empty.

     */

    #define list_first_entry(ptr, type, member) \

        list_entry((ptr)->next, type, member)

     

    /**

     * list_for_each    -    iterate over a list

     * @pos:    the &struct list_head to use as a loop cursor.

     * @head:    the head for your list.

     */

    #define list_for_each(pos, head) \

        for (pos = (head)->next; prefetch(pos->next), pos != (head); \

                pos = pos->next)

    在遍历时经常需要使用container_of和offset,例如list_for_each_entry(pos, head, member),就是遍历head链表,head链表的指针类型为 member(字符串),member是pos类型结构体的一个成员,再基于container_of得到结构体指针。[这点技巧在内核源码中经常能找到]

    2 链表使用举例

           下面以dmatest.c为例说明。需求:DMA测试程序需要实现多通道,且通道上支持多线程,需要支持能够互相访问。

    首先,因为需求互相访问,所以立即想到struct成员变量的方式,如下代码所示。

    struct channel_t{

        struct thread_t used[100];

    }

    struct info_t{

        struct channel_t used[100];

    };

    static struct info_t info;

           但是,缺点也很明显,申请了固定大小空间,要么浪费资源,要么资源不够。写到这,立即可以推出使用链表,但是内核提供的链表并没有数据域都是指针域,如何设计成为了关键。

           在这里,dmatest.c给出了参考答案,通过在每个成员中添加一个node节点,作为中介节点。如下所示。

    struct thread_t{

        struct list_head node;

    }

     

    struct channel_t{

        struct list_head node;

        struct list_head threads;

    }

     

    struct info_t{

        struct list_head channels;

    };

     

    static info_t info = {.channels = LIST_HEAD_INIT(&info.channels)}

           主要的操作包括。

    //构建通道与线程之间的关系

    list_add_tail(&thread->node, &dtc->threads);

    //构建驱动模块与通道之间的关系

    list_add_tail(&dtc->node, &info->channels);

    //构建通道与线程之间的关系

    list_add_tail(&thread->node, &dtc->threads);

    //构建驱动模块与通道之间的关系

    list_add_tail(&dtc->node, &info->channels);

    //遍历,因为已知的是模块内部声明的且唯一的info结构体,所以遍历按如下顺序

    list_for_each_entry(dtc, &info->channels, node) {

        struct dmatest_thread *thread;

        list_for_each_entry(thread, &dtc->threads, node) {

            if (!thread->done)

                return true;

        }

    }

    参考文献

    [1] http://www.cnblogs.com/Anker/p/3475643.html

    展开全文
  • C++链表操作总结和常见链表操作

    千次阅读 多人点赞 2017-02-26 21:13:34
    链表是一种动态数据结构,他的特点是用一组任意的存储单元(可以是连续的,也可以是不连续的)存放数据元素。链表中每一个元素成为“结点”,每一个结点都是由数据域和指针域组成的,每个结点中的指针域指向下一个...
  • LinkedList添加元素链表操作过程

    千次阅读 2019-02-01 16:16:38
    LinkedList添加元素链表操作过程1.LinkedList实现(基于jdk1.8)2.示例操作 1.LinkedList实现(基于jdk1.8) 底层通过操作双向链表实现数据存储,每个元素都包含有value值,指向前一节点和后一几点的引用; private...
  • 面试算法之链表操作集锦

    千次阅读 2013-09-04 21:24:34
    链表操作在面试过程中也是很重要的一部分,因为它和二叉树一样都涉及到大量指针的操作,而且链表本身很灵活,很考查编程功底,所以是很值得考的地方。下面是本文所要用到链表节点的定义: template struct ListNode...
  • python链表操作

    千次阅读 2018-08-22 09:20:53
    链表中的基本要素: 结点(也可以叫节点或元素),每一个结点有两个域,左边部份叫值域,用于存放用户数据;右边叫指针域,一般是存储着到下一个元素的指针 head结点,head是一个特殊的结节,head结点永远指向第一个...
  • 链表操作之插入数据

    千次阅读 2017-04-16 22:20:48
    链表插入操作
  • 双向链表操作 头文件定义 双向链表的初始化 双向链表的插入  双线链表求链表长度 双向链表的判空 双向链表的遍历  双向链表的查找(通过位置求值) 双向链表的检索(通过值求位置) 双向链表的删除  ...
  • JAVA链表操作

    千次阅读 2019-04-25 09:36:47
    //创建一个双向链表结点类,并用get,set方法获取其数据。 public class DNode { private int data;//数据域 private DNode next;//后继指针域 private DNode previous;//前驱指针域 public DNode(int data) { ...
  • 常见的链表操作

    千次阅读 2016-05-23 10:50:23
    1. 单链表的逆序包括逆序输出链表,三种方式,第一种是操作用栈的方式,将链表装入栈中,然后新建链表进行输出;第二种是头结点插入,没来一个节点,就插入头结点之后;第三种是对称交换,将链表以中心节点为中心,...
  • redis 链表操作

    千次阅读 2016-01-31 03:04:26
    1 link链表结构  把值插入链表头部  lpush key value 向左边插入  lpush character a  rpush character b  rpush key value 向右边插入 2 返回链表中的元素,start,stop   lrange key start stop  lrange
  • matlab实现链表操作

    千次阅读 2019-11-01 14:24:53
    实现的过程中采用了面向对象的编程概念,类似于C++中的class操作,这是之前没有接触到的知识。matlab定义类使用关键字classdef,详细使用方法可以参考help帮助文档。 1.建立链表首先建立节点类node,以下代码来至...
  • Redis Link链表操作

    千次阅读 2014-12-12 11:25:31
    把值插入到链表头部 lpush key value 返回并且删除链表尾部元素 rpop key 返回链表中起始位置的元素,左部从0开始,右部从-1开始 lrange key srart end 返回索引上的值 lindex key index ...
  • 数据结构-链表操作(创建、输出、查找、插入、删除等) C语言源码 #include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; typedef char datatype; typedef struct node { datatype data; struct node...
  • CSDN第一篇博客-C语言链表操作

    千次阅读 多人点赞 2019-03-31 11:26:24
    一个小白的C语言学习成长 ...用C语言首先构建链表的一系列的操作,其中包括链表的生成,链表的排序,链表的倒序,改变两两节点指向,头插法,尾插法等基本操作。直接上代码。代码中有详细的注解 5. typ...
  • SCAU高级语言程序设计--实验11 链表操作(1) 一、堂上限时习题 1、链表的合并 题目:下面程序创建两个链表,然后将第二个链表合并到第一个链表未尾,但合并部分的代码未完成,请你完成这部分代码。 #include ...
  • 常见链表操作之获取链表节点个数

    千次阅读 2018-01-17 11:11:02
    获取链表节点个数,是最简单的操作,需要注意链表是否为空! int GetListNodeLen(LIST_NODE * m_pHead) { if (m_pHead == NULL) { return 0; } LIST_NODE * pTemp = m_pHead; int aListLen = 0; while...
  • 利用二级指针进行链表操作

    千次阅读 多人点赞 2018-10-19 10:27:38
    常规的链表删除除了当前的遍历指针还需要维护一个prev指针,用来连接被删除节点的下一个节点,但实际上利用二级指针就可以避免多维护一个指针,使代码更加简洁。Linus的吐槽没错,到目前为止,我几乎没有在实际工作...
  • 带头结点的链表和不带头结点的链表主要不同点在插入和删除操作上。同时要注意,带头结点的链表初始化操作时建立头结点。 下面我们来看一下代码中的异同: #include #include #include typedef int elemType; ...
  • 用python实现链表操作

    千次阅读 2015-07-30 16:58:17
    用python实现初始化链表链表长度、插入、删除、新增、查找、逆序
  • 常用链表操作(1)-链表创建

    千次阅读 2015-02-28 22:03:20
    链表的插入和删除操作不用移动元素,适合经常需要改变元素的操作。链式存储可以方便的通过指针来操作,具有双线指针的存储结构可以较快的进行数据的访问。此种情况试用于双向链表。 创建链表的算法基本流程为: 1 ...
  • 若要对其他结点进行操作,必须对链表进行遍历,找到这个结点,然后进行相关操作。 遍历的代码一般是: for (Node x = first; x != null; x = x.next){ // 处理 x.item; } 链表的相关操作: 1.
  • PTA 带头节点的双向循环链表操作

    千次阅读 2020-06-24 13:00:04
    题目要求:读入一系列整数,依次插入到双向循环链表的头部和尾部,然后顺序和逆序输出链表。 输入格式: 输入一行整数(空格分隔),以-1结束。 输出格式: 第一行输出链表顺序遍历的结果,第二行输出逆序遍历的结果。...
  • linux驱动中的链表操作

    千次阅读 2015-06-12 16:27:24
    一、链表的基本概念 链表是一种物理存储单元上非连续的存储结构,数据单元的逻辑顺序是通过链表中的指针链接次序实现的。通常链表有单向链表和双向链表,如下图所示:
  • 思路就是有两个指针P1和P2,同时从头结点开始往下遍历链表中的所有节点。 P1是慢指针,一次遍历一个节点。 P2是快指针,一次遍历两个节点。 如果链表中没有环,P2和P1会先后遍历完所有的节点。 如果链表中有环,...
  • 单向链表操作函数

    千次阅读 2014-09-12 15:18:16
    创建链表函数: STU *create_link(STU *head,STU *p_new) { STU *p_mov=head; if(head==NULL) { head=p_new; p_new->next=NULL; } else { while(p_mov->next!=NULL) p_mov=p_mov->...
  • 给出任意单向链表,找出并返回该链表的中间节点。 奇数长度的链表,例如:1-&gt;2-&gt;3-&gt;4-&gt;5 返回节点 3 偶长度的链表,例如:1-&gt;2-&gt;3-&gt;4-&gt;5-&gt;6 返回...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 483,384
精华内容 193,353
关键字:

链表的操作