数据结构--->第二天,链表

链表


        特点 
            地址可以不连续 大小不固定 
            删除和插入的时候,不需要移动元素,比较方便
            访问不方便,只能从头结点开始访问


        术语
            单向
                链表中任意一个结点,只有一个指针域,存放下一个结点的地址。

        单向循环链表
               特点:
                    链表 + 尾结点指向头结点
               注意:
    在单向不循环链表的基础上修改判断尾结点的条件。 p->pNext == NULL ==> p->pNext == pList


            双向
      链表中任意一个结点,有两个指针域,分别存放下一个结点的地址和前一个结点的地址。  
           双向循环链表
    笔试题:
        1. 合并两个已知尾结点的单向循环链表。

方法一

方法二


        2. 合并两个有序链表,使它成为一个有序链表。
        3. 链表排序
        4. 链表逆序
        5. 链表的删除
        注意: 
            写一个函数API来实现上面的某个功能
            在这个API中尽量不要出现malloc。            
            头结点
                数据域为空(数据域不存放有效数据)
            首结点
                头结点的下一个结点
            尾结点    
                链表中某个结点的指针域为空,就是尾结点。
            循环
                尾结点保存头结点的地址
            空链表
                头结点的指针域为空就是空链表。
            带头结点的单向不循环的链表 --- 链表
        定义一个数据类型来描述链表
            struct student
            {};
            typedef struct student data_t;
            struct  node
            {
                data_t data; //数据域
                struct node * pNext; //指针域
            };
            typedef struct node LIST;
        相关操作
            创建链表

//函数功能:创建线性表
  7 LIST * createList( )
  8 {
  9     LIST * pList = NULL;
 10 
 11     pList = ( LIST * )malloc( sizeof(LIST) );
 12     if ( NULL != pList )
 13     {
 14         memset( pList, 0, sizeof(LIST) ); //空链表
 15     }
 16     return pList;
 17 }


            插入

        //头插
 23     //1.堆区新建结点
 24     LIST * pNew=NULL;
 25     pNew=(LIST *)malloc(sizeof(LIST));
 26     if(NULL==pNew)
 27     {
 28         return ERROR;
 29     }
 30     //2.初始化新结点
 31     memset(pNew,0,sizeof(LIST));                                            
 32     pNew->data=newData;//要插入的数据
 33 
 34     //3.链接
 35     if(HEAD==offset)
 36     {
 37         //保护头结点之后的数据
 38         pNew->pNext=pList->pNext;
 39         //插入
 40         pList->pNext=pNew;
 41     }


            查询 


            修改


            删除

        LIST *p=NULL;
145     LIST *q=NULL;
146     int i;
147     //头删
148     if(NULL==pList)
149     {
150         return ERROR;
151     }
152     if(HEAD==offset)
153     {
154         //1.p指向被删除的结点(首结点)
155         p=pList->pNext;
156         //2.保护p后面的所有结点
157         pList->pNext=p->pNext;
158         //3.保存被删除的数据                                                
159         *pData=p->data;
160         //4.释放p
161         free(p);
162         p=NULL;
163     }

        //中间删
165     else
166     {
167         q=pList;
168         p=pList->pNext;
169         for(i=0;i<offset-1 && p;i++)
170         {
171             q=q->pNext;
172             p=p->pNext;
173         }
174         //判断是否为尾结点
175         if(!p)
176         {
177             return ERROR;
178 
179         }                                                                   
180         //判断pData是否是指针
181         if(pData)
182             *pData=p->data;
183         q->pNext=p->pNext;
184         free(p);p=NULL;
         }    

        //尾删
188     else if(TAIL==offset)
189     {
190         //1.p指向尾结点,并且q指向尾结点的前一个结点
191         q=pList;
192         p=pList->pNext;
193         //判断p是不是尾结点
194         while(NULL!=p->pNext)
195         {                                                                   
196             //p不是尾结点
197             //向后移动p和q
198             q=q->pNext;
199             p=p->pNext;
200         }
201         //13.将q作为新的尾结点
202         q->pNext=NULL;
203         //3.保存p的数据
204         *pData=p->data;
205         //4.释放p
206         free(p);
207         p=NULL;
208     }


            显示

//函数功能:显示链表中的元素
 83 void showList( LIST * pList )
 84 {
 85     LIST *p=NULL;
 86     if(NULL==pList || NULL==pList->pNext)
 87     {
 88         return;
 89     }
 90     //1.p指向首结点                                                         
 91     p=pList->pNext;
 92     //2.判断p是否为空,如果空,就结束。如果不为空,就输出p的数据
 93     while(NULL!=p)
 94     {
 95             printf("%d ",p->data);
 96             //3.p向后移动
 97             p=p->pNext;
 98     }
 99     printf("\n");
100 }


            销毁链表
    

    测试代码:
            int  main()
            {
                创建链表
                把信息插入链表中
                查询 
                修改
                删除
                显示
                销毁链表
            }

#include <stdio.h>
#include "list.h"

int main(int argc, const char *argv[])
{
	//创建链表
	LIST *pList=NULL;
	pList=createList();
	
	//插入数据到链表
	int i;
	for(i=15;i>8;i--)
	{
		//头插
		insertDataToList(pList,i,HEAD);
	}
	//尾巴插入
	insertDataToList(pList,444,TAIL);
	//中间插入
	insertDataToList(pList,6666,2);

	//显示链表中的元素
	showList(pList);

	//查询
	int ret1;
	ret1=searchList(pList,6666);
	if(0>ret1)
	{
		printf("search error\n");
		return ERROR;
	}
	printf("要查询数字存在\n");

	//修改
	int ret2;
	ret2=updateList(pList,10,999);
	if(0>ret2)
	{
		printf("update error\n");
		return ERROR;
	}

	//删除链表中的元素
	data_t pData;
	int ret3;
	ret3=deleteFromList(pList,TAIL,&pData);
	if(0>ret3)
	{
		printf("success error\n");
		return ERROR;
	}
    //显示链表中的元素
	showList(pList);

	//销毁链表
	destroyList(pList);
	return 0;
}


    
    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值