线性表的相关操作、linear list

线性表:

顺序表

1:线性表定义:n个数据元素的有限序列,可以为空
2:线性表的顺序表示:用一组地址连续的存储单元依次存储线性表中的数据元素,顺序的意思是:地址顺序。优点:便于随机存取
3:对于一个长度为n的顺序表,在任何位置上插入或删除操作都是等概率的情况下,则插入一个元素时平均移动表中 (n+0)/2 个元素
4:在长度为n的顺序表的表尾插入一个新元素的时间复杂度为:O(1) 因为顺序表特性:随机存取

C语言实现(软件:Dev-C++):
欢迎大家批评指正


#define List_init_size 100 //初始 
#define listincrement  10 //增量 
#define  Status int
#define ok 0
#define Error -1
#define MaxSize 100
typedef int Elemtype;

typedef struct{
	Elemtype *elem;
	Elemtype length;
	Elemtype listsize;//当前分配的存储容量 
}SqList;
//--------------上面的是放在Sqlist.h文件下--------------//
#include "Sqlist.h"
#include "stdio.h"
#include <malloc.h>
//----------------------初始化(木有设头结点)-----------//
Status Initlist_Sq(SqList *L){ //初始化步骤:分配基址 长度 容量 
	L->elem=(Elemtype *)malloc(List_init_size*sizeof(Elemtype));//分配预定义空间 
	if(!(L->elem)) return Error;
	L->length=0;//初始长度为0
	L->listsize=List_init_size;//容量为初始容量
	return ok;	
}
//---------------------------线性表的插入-----------------//
Status ListInsert_Sq(SqList *L,int i,Elemtype e){//在线性表i位置插入e元素{
   if(i<1||i>L->length+1) return Error;
   Elemtype *p=&(L->elem[L->length-1]),*newbase; //p指向最后一个数据
   if(L->length>=L->L->listsize){
    newbase=(Elemtype *)malloc(sizeof(Elemtype)*(L->listsize+listincrement));
    L->elem=newbase;
    L->listsize+=listincremen;
   }
   Elemtype *q=&(L->elem[i-1]);//q为插入位置
   for(:p>q;--p){
   *(p+1)=*p;//移位
   }
   *q=e,++L->length;
   return ok;
}
//-------------------------删除--------------------------//
Status ListDelete_Sq(SqList *L,int i,Elemtype *e){//删除第i个位置的元素 用e返回 
       if(i<1||i>L->length) return Error;
       Elemtype *p,*q;
       p=&(L->elem[i-1]);//p来定位
       *e=*p;
       q=L->elem+L->length+1;//q定位于表尾
       for(++p;p<=q;++p){
       	    *(p-1)=*p; 
	     --(L->length);
       }
       return ok;
}
//-------------------------获取第i个元素--------------------//
Status GetElement_Sq(SqList *L, int i, Elemtype *e){
       if(i<1||i>L->length) return Error;
       *e=*(L-elem+i-1);
       return ok;
}
//---------------------遍历每一个元素---------------//
Status VisitElem_Sq(SqList *L){
       Elemtype e,*p=L->elem;//指向表头
       for(;p<&(l->elem[l->length-1]);p++){
		e=*p,printf("L链表的元素:%d\n",e);
	}
	return ok;
}

//----------------A和B都是非递减有序合并在A表(非递减有序)-----------------//
Status TwoListSortMethod(Sqist *A,SqList *B){
       if(A->length+B->length>MaxSize){
       return -1;
       }
       int i=A->length,j=B->length;
       while(j>0){
          if(i==0||A->elem[i-1]<B->elem[j-1]){
          A->elem[i-1+j]=B->elem[j-1];//B[j-1]是第i+j大的元素
          --j;
          }else{
          A-elem[i-1+j]=A[i-1];//A[i-1]是第i-i+j大的元素
          ++i;         
          }
       }A->length=A->length+B->length;
}
//-----------------------A和B表相同的元素入C表----------------------//
Status A_elemEqualB_elemSort_end(SqList *A,SqList *B,SqList *c){//递增表尾排序合C法
       Initlist_Sq(c); 
       if(C->listsize<A->length+B->length) return -1;
       int i=A->length-1,j=B->length-1,k=0;
       while(i>=0 && j>=0){
         if(A->elem[i]>B->elem[j]) --i;
         else if(A->elem[i]<B->elem[j]) --j;
         else{
          C->elem[k++]=A->elem[i];
          (C-length)++;
         --i,--j;
          }
      }return ok;
}
//---------------------保存A,B元素 重复元素只能保存一个------------------------//
Status SavaOnlyoneInCList(SqList *A,SqList *B,SqList *c){
	//A.B非递减顺序表合并(重复元素只保存一个)《数据结构》P10.7 
	Initlist_Sq(c);
	int i=0,j=0,k=0;
	while(i<=A->length && j<=B->length){
		if(A->elem[i]<B->elem[j]) c->elem[k++]=A->elem[i],++i,c->length++;
		else if(A->elem[i]>B->elem[j]) c->elem[k++]=B->elem[j],++j,c->length++;
		else{
		c->elem[k++]=A->elem[i];
		c->length++;
		i++;
		j++;
		} 
	}
}
//---------------------test-------------------//
void LinearlistTest(){
	SqList la;
	Elemtype e;
	Initlist_Sq(&la);
	int i=0,j=0;
	for(i=1;i<10;i++){
		scanf("%d",&j);
		ListInsert_Sq(&la,i,j);
	}
	VisitElem_Sq(&la);
	GetElement_Sq(&la,3,&e);
	ListDelete_Sq(&la,3,&e);
}


线性链表:

1:特点:用一组任意的存储单元存储线性表的数据元素
2:头指针(L)指示链表中第一个结点的存储位置
3:优点:便于插入和删除(需要移动指针)
4:头结点:第一个数据结点之前附设的一个结点,其(头结点)指针域指向第一个数据结点(严蔚敏版为第一个结点),若线性表为空表,则(头结点)指针域为空(L->next==NULL),设置头结点的目的方便一些操作的实现(统一相关操作,譬如:在第一个数据结点之前插入或者删除结点,这些操作就统一了)
5:一个具有n个结点的有序单链表查找其值为x的结点,在查找成功的前提下,需要平均比较(n+1)/2个结点
6:循环链表的主要优点:从表中任一结点出发都能扫描整个链表
7:非空循环单链表head的链尾结点(p所指)满足:p->next = =head
8:单链表实施插入和删除操作:不需要移动结点,只需改变结点指针
9:给定有n个元素的一维数组,建立一个有序的单链表的时间复杂度为O(n^2),因为:设m为操作次数,则m=n*(n+1)/2.
10:链表的头指针L指向其第一个结点,有标示链表的作用。若链表有头结点,无论链表是否为空,头指针均不空
11:存储密度(结点值域所占存储量/结点结构所占存储量)。顺序表存储密度=1,链表存储密度<1
12:单链表的首结点就是就是单链表的第一个结点,亦是第一个数据结点
13:删除q的后继结点: p=q->next,q->next=p->next
14:删除双向链表的一个结点:修改两个指针;在双向链表插入一个结点:修改四个指针
15:由尾指针rear指示的循环单链表,在表尾插入一个结点s的操作:s->next=rear->next,rear->next=s,rear=s;

typedef  int Elemtype;
typedef  int Status;
#define  ok  0
#define Error -1
typedef struct LDataNode{
	Elemtype x;
	struct LDataNode *next;//结点指针
}LDataNode;
typedef struct LHNode{
	LDataNode *next; //
	LDataNode *tail; //尾
}LHNode,*LinkList;//带尾指针的链表
//-------------------初始化----------------//
Status InitLink(LinkList *head){//指向**链表结构体指针**的指针(指向指针的指针)
       *head=(LinkList)malloc(sizeof(LHNode));
       LDataNode *p=(LDataNode *)malloc(sizeof(LDataNode));//数据首元结点指针,增设辅助结点的操作很常见,特别是在遍历的时候
       if(*head==NULL || p==NULL) return Error;
       p->next=NULL,(*head)->next=p,(*head)->tail=p;
       return ok;
}
//-------------------加入元素----------------//
Status AddElem(LinkList *head,Elemtype e){
       LDataNode *p=(LDataNode *)malloc(sizeof(LDataNode));//让每次进来的e都有个温暖的家(结点)
       if(p==NULL) return Error;
       p->next=NULL,p->x=e;
       (*head)->tail->next=p;//上一个指针域的结点指向p
       (*head)->tail=p;//更新指针
       return ok;

}
//-------------------遍历----------------//
Status LTraverse(LinkList head){//结构体指针
      LDataNode *p=head->next->next;//p指向首元结点
      while(p){
      printf("%d",p->x);
      p=p->next;
      }printf("\n);
      return ok;
}
//-------------------删除----------------//
Status Deletelist(LinkList *head,int i,Elemtype *e){//删除第i个结点并用e返回 
       if(i<1) return Error;
       int j=1;
       LDataNode *p=(*head)->next;//指向首元结点
       while(num!=i&&p->next!=NULL){//p移动到第j-1结点
       p=p->next;
       j++;
       }
       if(p->next==NULLreturn Error;
       *e=p->next->x;
       p->next=p->next-next;//修改指针 这就是为什么要移动到第j-1个结点
       return ok;
}
//------------递归求链表最大值----------------------//
Status  GetMax(LDataNode *p){///进来的是首元结点指针
        if(p->next==NULL) return p->x;//只有一个结点
        int j=GetMax(p->next);
        if(p->x>j) return p->x;
        else return j;
}
//----------递归求数据结点的个数-----------------//
Status GetNum(LDataNode *p){
       if(p->next==NULL) return 1;
       
       return 1+GetNum(p->next);
}
//-----------用于逆置链表的遍历--------------------//
Status NewLTraverse(LinkList head){//遍历链表 
	LDataNode *p=head->next;//指向第二个结点(第一个结点是没有数据的) 
    while(p->next){
    	printf("%d",p->x);
    	p=p->next;
	} 
    printf("\n");
	return ok; 
	 
}
//---------------逆置----------------------//
Status InverseList(LinkList *L){
        LDataNode  *p=(*L)->next;//指向首元结点
        (*L)->next=NULL;
        while(p){
        LDataNode *pre=p->next;
        p->next=(*L)->next;
       (*L)->next=p;
        p=pre;
        }
}
void LinkListTest(){
  
  LinkList head;
  InitLink(&head); 
  int i=0;
   
  for(;i<10;i++){
  	AddElem(&head,i);
  }
  LTraverse(head);
  int e;
  DeleteList(&head,3,&e);
  printf("%d\n",e);
  LTraverse(head);
  InverseList(&head);
  NewLTraverse(head);
} 

  • 9
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值