链式存储——链表及相关操作

  • 定义

    • n个节点离散

    • 彼此通过指针相连

    • 每个节点只有一个前驱节点;也只有一个后续节点

    • 首节点没有前驱节点,尾节点没有后续节点

  • 注意区别

    为什么引入头节点?

    ——为了便于对链表的操作

    • 头节点:第一个有效节点之前的节点,头节点并不存放有效数据,头节点的数据类型和首节点的一样
    • 头指针:指向头节点的指针变量
    • 首节点:第一个有效节点
    • 尾节点:最后一个有效节点,指针域为NULL
    • 尾指针:指向尾节点的指针变量

    —确定一个量表需要几个参数?

    ——仅需头指针即可,其他信息都可求

  • 分类

    • 单链表
    • 双链表:每个节点有两个指针域
    • 循环链表:表中最后一个结点的指针域指向头结点,整个链表形成一个环
    • 非循环链表
  • 对链表的操作

    • 创建

    • 遍历

    • 插入节点

    • 删除节点

    • 查找

    • 销毁

    • 求长度

    • 排序

      #include<stdio.h>
      #include<malloc.h>
      #include<stdlib.h>
      
      typedef struct Node
      {	
      	//数据域 
      	int data;
      	//指针域
      	struct Node * pNext;//因为它要指向的是下一个节点(struct Node类型) 
      }NODE,*PNODE;
      
      /*
      NODE等价于 struct Node  
      *PNODE等价于struct Node * 
      */
       
      PNODE createList(); 				//创建链表,并返回头指针
      void traverseList(PNODE);			//遍历输出
      bool isEmpty(PNODE);				//判空
      int lengthList(PNODE);				//求链表长度	
      bool insertList(PNODE,int,int);		//插入元素
      bool deleteList(PNODE,int,int *); 	//删除元素
      void sortList(PNODE);				//从大到小排序
      
      int main()
      {
      	PNODE pHead = NULL;//等价于struct Node * pHead = NULL 
      	int val;
      	pHead = createList();//创建一个非循环单链表,并将该链表的头节点返回,赋给pHead 
      	
      	printf("原链表:-------------\n"); 
      	traverseList(pHead);
      	
      	if(isEmpty(pHead))
      	{
      		printf("该链表为空"); 
      	}
      	printf("链表的长度是:%d\n",lengthList(pHead));  
      	
      	printf("排序:-------------\n"); 
      	sortList(pHead);
      	traverseList(pHead);
      	
      	printf("插入:-------------\n");
      	insertList(pHead,4,100);
      	traverseList(pHead);
      	
      	printf("删除:-------------\n");	 
      	if(deleteList(pHead,4,&val)) 
      	{
      		printf("删除成功,您删除了元素:%d",val);
      	}
      	else
      	{
      		printf("删除失败");
      	}
      	
      	
      	return 0;
      } 
      
      PNODE createList(void)
      {
      	int len;
      	int val;//用来临时存放用户输入的节点的值 
      	PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配了一个不存放一个有效数据的头节点 
      	if(NULL == pHead)
      	{
      		printf("内存不足,分配失败\n");
      		exit(-1);
      	}
      	printf("请输入您要生成的链表节点个数:len = ");
      	scanf("%d",&len); 
      	
      	PNODE pTail = pHead; //这里和 57 59行是关键
      	pTail->pNext = NULL; 
      	
      	for(int i = 0;i<len;i++)
      	{
      		printf("请输入第%d个节点的值:",i+1);
      		scanf("%d",&val);
      		
      		PNODE pNew = (PNODE)malloc(sizeof(NODE));
      		if(NULL == pNew)
      			{
      				printf("内存不足,分配失败\n");
      				exit(-1);
      			}
      		pNew->data = val; 
      		pTail->pNext = pNew;//pTail永远指向尾节点 57行 
      		pNew->pNext = NULL;
      		pTail = pNew; //59行 
      	}
      	return pHead; 
      	
      }
      
      void traverseList(PNODE pHead)
      {
      	PNODE pTemp = pHead->pNext;
      	while(pTemp!= NULL)  
      	{
      		printf("%d\n",pTemp->data);
      		pTemp = pTemp->pNext;
      	}
      	return; 
      } 
      
      bool isEmpty(PNODE pHead)
      {
      	if(pHead->pNext==NULL)
      	{
      		return true; 
      	}
      	else 
      		return false;
      }
      
      int lengthList(PNODE pHead)
      {
      	int count = 0;
      	PNODE p = pHead->pNext;
      	while(p!=NULL)
      	{
      		count++;
      		p = p->pNext;
      	}
      	return count;
      }
      
      void sortList(PNODE pHead)
      {
      	int temp;
      	PNODE p;
      	int i,j;
      	int len = lengthList(pHead);
      	if(!isEmpty(pHead))
      	{
      		for(i = 1;i<len;i++)
      		{
      			for(j = 0,p = pHead->pNext;j<len-i;j++,p = p->pNext)
      			{
      				if(p->data < p->pNext->data)
      				{
      					temp = p->data;
      					p->data = p->pNext->data;
      					p->pNext->data = temp;
      				}
      			}
      		}
      	}
      }
      
      //在pHead所指向的链表的第pos个节点的前面插入一个新的节点,该节点的值是val,并且pos的值是从1开始的 
      bool insertList(PNODE pHead,int pos,int val)
      {
      	int i = 0;
      	PNODE p = pHead;
      	while(NULL!=p&&i<pos-1)	
      	{
      		p = p->pNext;
      		i++;
      	}
      	if(i>pos-1||NULL == p)
      	{
      		return false;
      	}
      	
      	PNODE pNew = (PNODE)malloc(sizeof(NODE));
      	if(NULL == pNew)
      	{
      		printf("内存不足,分配失败\n");
      		exit(-1);
      	}
      	
      	pNew->data = val;
      	PNODE q = p->pNext;
      	p->pNext = pNew;
      	pNew->pNext = q;
      	
      	return true;
      } 
      
      bool deleteList(PNODE pHead,int pos,int * pVal)
      {
      	int i = 0;
      	PNODE p = pHead;
      	while(NULL!=p->pNext&&i<pos-1)	
      	{
      		p = p->pNext;
      		i++;
      	}
      	if(i>pos-1||NULL == p->pNext)
      	{
      		return false;
      	}
      	
      	PNODE q = p->pNext;
      	*pVal = q->data;
      	//删除p节点后面的节点 
      	p->pNext = q->pNext;
      	free(q);
      	q=NULL;
      	
      	return true;
      }
       
      

      image-20200624221905635

  • 算法

    • 狭义的算法与数据的存储方式有关
    • 广义的算法与数据的存储方式无关
    • 泛型:
      • 利用某种技术使得不同的数据存储方式,执行操作一致
  • 链表的优缺点

    • 优点

      • 插入和删除速度快
      • 存储容量无限
    • 缺点

      • 存储速度慢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值