链表

如何实现链表?

C语言中可以使用指针和动态分配内存函数malloc来实现。

 

指针

int a;  
int *p;


指针有什么作用?答案:存储一个地址。确切的说是存储一个内存空间的地址。

p=&a;

&叫做取地址符。这样p就获得(存储)了整形变量a的地址,可以理解成整形指针p指向了整形变量a。p指向a之后,我们可以用指针p来操作变量a了。

#include<stdio.h>  
	int main()  
	{  
	  
	 int a=10;  
	 int p;  
	 p=&a;  
	 printf("%d",*p);  
	getchar();getchar();  
	return 0;  
}  

*这个符号叫做间接运算符,作用是取得指针p所指向的内存中的值。



c语言*号有3个用途,分别是:

乘号、

申明一个指针,在定义指针变量时使用、

间接运算符,取得指针所指向的内存中的值。

 

 

malloc函数的作用是从内存中申请分配指定字节大小的内存空间。

int *p;  
p=(int *)malloc(sizeof(int));

注意:malloc函数的返回类型是void *,void *表示未确定类型的指针。在C/C++中,void*类型可以强制转换为任何其他类型的指针。上述代码我们将其强制转换为整形指针。

 

指针用来存储内存地址,为什么要区分不同类型指针?

因为指针变量存储的是一个内存空间的首地址(第一个字节的地址),但是这个空间占用了多少个字节,用来存储什么类型的数,则是由指针的类型来标明。占用系统才知道应该取多少个连续内存作为一个数据。

#include<stdio.h>  
#include<stdlib.h>//注意程序中使用malloc函数时需要用到stdlib.h的头文件  
int main()  
	{  
	  
	int *p;//定义一个指针p   
	 p= (int*)malloc(sizeof(int));//指针p获取动态分配的内存空间地址   
		*p=10;//向指针p所指向的内存空间存入10   
	printf("%d",*p);//输出指针p所指向的内存中的值   
	getchar();getchar();  
 	return 0;  
}  


有了malloc函数可以在程序运行过程中根据实际情况来申请空间。

 

如何建立链表?

首先需要一个头指针head指向链表的最开始。当链表还没有建立的时候头指针head为空(也可以理解为指向空结点)

struct  node *head;  
head=NULL;

创建第一个结点,并用临时指针 p 指向这个结点。

struct  node *q;  
p=(struct node *)malloc(sizeof(struct node));//动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点 

接下来分别设置新创建的这个结点的左半部分和右半部分。

scanf("%d",&a);  
p->data=a;//将数据存储到当前结点的data域  
p->next=NULL;//设置当前结点的后继指针指向空,也就是当前结点的下一个结点为空  

设置头指针并设置新创建结点的 *next 指向空。头指针的作用是方便以后从头遍历整个链表。

if(head==NULL)  head=p;//如果是新创建第一个结点,则将头指针指向这个结点  
else q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点  

最后将指针q也指向当前结点,因为临时指针p将会指向新创建的结点。

q=p;

完整代码:

#include<stdio.h>  
#include<stdlib.h>//注意程序中使用malloc函数时需要用到stdlib.h的头文件  
struct node{  
	int data;  
	struct node *next;  
};  
int main() {  
	struct  node *head,*p,*q,*t;  
	int i,n,a;  
	scanf("%d",&n);  
	head=NULL;  
	for(i=1;i<=n;i++) {  
    scanf("%d",&a);  
	p=(struct node *)malloc(sizeof(struct node));  
	p->data=a;  
	p->next=NULL;  
	if(head==NULL)  head=p;  
	else q->next=p;  
	          
	 q=p;  
	}  
    //输出链表中的所有数   
	t=head;  
	while(t!=NULL) {  
	    printf("%d ",t->data);  
	    t=t->next;//继续下一个结点   
	  
	getchar();getchar();  
    return 0;  
}  

测试数据:

9

2 3 5 8 9 10 18 26 32


往创建好的链表中插入6,使得链表有序。

首先用一个临时指针t从链表的头部开始遍历。

t=head; 
等到指针 t 的下一个结点的值比 6 大的时候,将 6 插入到中间。即 t->next->data 大于 6 时插入:

#include<stdio.h>  
#include<stdlib.h>//注意程序中使用malloc函数时需要用到stdlib.h的头文件  
struct node{//创建一个结构体用来表示链表的结点类型   
int data;  
struct node *next;  
};  
int main() {  
	struct  node *head,*p,*q,*t;  
	int i,n,a,b;  
	scanf("%d",&n);  
	head=NULL;//头指针初始化为空   
	for(i=1;i<=n;i++) {  
	    scanf("%d",&a);  
        p=(struct node *)malloc(sizeof(struct node));//动态申请一个空间,用来存放一个结点,并用临时指针p指向这个结点   
	    p->data=a;//将数据存储到当前结点的data域中   
        p->next=NULL;//设置当前结点的后继指针指向空,也就是当前结点的下一个结点为空  
          
       if(head==NULL)  head=p;//如果是新创建第一个结点,则将头指针指向这个结点  
       else q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点  
         
       q=p;//指针q也指向当前结点,因为临时指针p将会指向新创建的结点。  
    }  
	      
    scanf("%d",b); //读入待插入的数   
    t=head;//从链表头部开始遍历   
    while(t!=NULL) {//当没有道德链表尾部的时候循环  
        //如果当前结点是最后一个结点或者下一个结点的值大于带插入数的时候插入   
	        if(t->next==NULL || t->next->data >b) {  
           p=(struct node *)malloc(sizeof(struct node));  
           p->data=a;  
           p->next=t->next;  
           t->next=p;  
            break;  
        }  
        t=t->next;//继续下一个结点   
    }  
     
    //输出链表中的所有数  
    t=head;   
    while(t!=NULL) {  
        printf("%d ",t->data);  
        t=t->next;//继续下一个结点   
	    }  
	      
   getchar();getchar();  
    return 0;  
};  



模拟链表

使用数组来实现链表叫做模拟链表。用一个数组right来存放序列中每一个数右边的数是谁即可。

data

1

2

3

4

5

6

7

8

9

10

2

3

5

8

9

10

18

26

32

 

 

right

1

2

3

4

5

6

7

8

9

10

2

3

4

5

6

7

8

9

0

 

 

data数组是用来存放序列中具体数字的,right数组用来存放当前序列中每一个元素右边的元素在数组data中位置的。例如right[1]=2,表示当前序列1号元素右边的元素存放在data[2]中。right[9]=0表示当前序列9号元素右边没有元素。

 

现在往当前序列加入一个6:

 

data'

1

2

3

4

5

6

7

8

9

10

2

3

5

8

9

10

18

26

32

6

 

right'

1

2

3

4

5

6

7

8

9

10

2

3

10

5

6

7

8

9

0

4


#include<stdio.h>  
int main() {  
	int data[101],right[101];  
    int i,n,t,len;  
    scanf("%d",&n);  
    for(i=1;i<=n;i++)   
        scanf("%d",&data[i]);  
    len=n;  
    //初始化数组right   
    for(i=1;i<=n;i++) {  
       if(i!=n) right[i]=i+1;  
       else right[i]=0;  
    }     
    //直接在数组data的末尾增加一个数   
   len++;  
   scanf("%d",&data[len]);  
   //从链表的头部开始遍历   
   t=1;  
   while(t!=0) {  
       if(data[right[t]] > data[len]) {//如果当前结点下一个结点的值大于待插入数,将数插入中间   
            right[len]=right[t];//新插入数的下一个结点标号等于当前结点的下一个结点编号   
           right[t]=len;//当前结点的下一个结点编号就是新插入数的编号   
            break;//插入完成跳出循环   
        }  
        t=right[t];  
    }  
    t=1;  
    while(t!=0) {  
        printf("%d ",data[t]);  
        t=right[t];  
    }  
    getchar();getchar();  
    return 0;  
};  

测试数据:

9

23 5 8 9 10 18 26 32

6







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值