一:线性表:链表的初始化操作及应用

节点结构

typedef struct LNode
{
	int  data;			//数据域
	struct LNode *next;		//指针域
}LNode, *Linklist;
// LNode, 结构体类型名,描述链表中的结点类型
// LinkList ,结构体指针类型名,用来说明“单链表类型的”变量
//基础知识::小细节
// LNode *p; LinkList L;
// p 为单链表结点的指针(p指向结点),
// L 标记一具体的单链表。。

InitList(*L):初始化一个线性表

int Init_List ( LinkList  &L ) {
       //L是带头结点的单链表的头指针
       // L = new LNode;这样也行,虽然申请的是结构体,但是返回是个指针类型
	L=(Linklist)malloc(sizeof(LNode))  //申请头结点
	if(!L) exit(-2);
	L->next=NULL;
	return 1;
}

ListEmpty(L):判断是否为空表

int ListEmpty(Linklist L){
    if(L->next){
        return 0;
    }else {
        return 1;
    }
}

ClearList(*L):清空线性表

int ClearList(Linklist &L)
{
	Linklist p,q;
	p = L->next;//指向头结点
	while(p)
	{
		q = p->next;
		free(p);
		p = q;
	}
	return OK;
}

ListLength(*L):链表的表长

int ListLength(Linklist L){
    Linklist p;
    p=L->next;
    int j=0;
    while(p){
        j++;
        p=p->next;
    }
    return j;
}

GetElem(L,i,*e):将表中的第i个元素,返回给e

int GetElem(Linklist L,int i, int &e)
{
	Linklist p= L; //定义临时指针p:外指
	int k = 0;
	while(p && k< i-1)	//第i个的前一个
	{
		p = p->next;
		k++;
	}

	if(!p || k> i-1)
	{
		return ERROR;
	}
	e = p->next->data;
	return OK;
}

LocateElem(L,e):查找表中e相等元素序号

int LocateElem(Linklist L,int e){
    Linklist p=L->next;
    int j=1;
    while(p&&p->data!=e){
        p=p->next;
        j++;
    }
    if(p)return j;
    else return 0;
}

ListInsert(L,i,e):在线性表的第i个位置插入元素e

这个是带有头结点的:

int ListInsert(Linklist &L,int i,int e)
{
	int j = 1;
	Linklist p = L;

	while( p && j < i)		//找到j=i,temp是目标结点的前一个结点
	{
		p = p->next;
		j++;
	}

	if(!p || j > i)
	{
		return ERROR;
	}

	Linklist q = (Linklist)malloc(sizeof(Node));//动态申请内存,链表的意义(随时扩容)
	q->data = e;
	q->next = p->next;
	p->next = q;

	return OK;
}

这个是不带有头结点的:

Status ListInsert( LinkList &L,  int i,  ElemType e )  {
     // L是不带头结点的单链表,在ai之前插入新结点e
   if(i<=0) return ERROR; //i太小,非法
   if(i==1){s=new Lnode; s->data=e; s->next=L; L=s;}
   else {
      p=L; j=0;  //p指向头结点,j是计数器
      while(p && j<i-1){p=p->next; j++;}  //令p指向ai-1
      if(!p) return ERROR;         //i太大,非法
      s=new Lnode;s->data=e;
      s->next=p->next;  p->next=s; } //修改指针
        return OK;
}

ListDelete(*L,i,*e):删除线性表中的第i个元素,并将值返回给e

int ListDelete(Listlink &L,int i,int &e)
{
	int j = 1;
	Linklist  p = L;

	while( p && j < i)		//找到要删除的前一结点
	{
		p = p ->next;
		j++;
	}

	if(!p || j > i)
	{
		return ERROR;
	}

	Linklist q = p->next;			//要删除的结点
	e = q->data;
	p->next = q ->next;
	free(q);

	return OK;
}

ListLength(L): 返回线性表元素的个数

int  ListLength ( LinkList  L )  {
	// L是带头结点的单链表
	Linklist p=L->next;
	int n=0;
	while(p) {
	    n++;
	     p=p->next;
    }
	return (n);
}

头插法插入元素创建链表

void  CreatList1( LinkList  &L,int n )  {
//逆位序输入n个元素的值,建立带结点的单链表L
   L=new LNode;   //申请头结点
   L->next=NULL;
   for(int i=n;i>0;i--){
     
     s=(LNode*)malloc(sizeof(LNode));   //申请新结点
     scanf(&e);           //从键盘输入一个元素值
     s->data=e;
     s->next=L->next;
     L->next=s;      //插入链表
   }   // for
}

尾插法插入元素创建链表

void  CreateList2( LinkList  &L,int n )  {
//从键盘正序输入n个元素值,按尾插法创建带头结点的单链表L
   L=new LNode; L->next=NULL;  //定义头结点
   r=L;             //r是L的尾指针
   for(int i=n;i>0;i--){
     scanf(&e); //从键盘输入一个元素值
     s=new LNode;   //申请新结点
     s->data=e;
	 s->next=NULL; 
	 r->next=s; //将s插入链表尾
     r=s; //修改尾指针
    }   // for
}

求两个线性表La和Lb的并集

void Union(Linklist &La,  Linklist &Lb){
    La_len=ListLength(La);
    char e;
    while(!EmptyList(Lb)){
            ListDelete(Lb,1,e);
            if(!LocateElem(La,e)){
                ListInsert(La,++La_len,e);
            }
    }
    Destory(Lb);
}

求两个线性表La和Lb的交集

void Intersect(Linklist &La, Linklist &Lb){
    int i=1;
    int e;
	while(i<=ListLength(La)){
	 GetElem(La, i, e);
	 if(!LocateElem(Lb, e)) {ListDelete(La, i, e);}
	 else   i++;
	}
  Destroy(Lb);  //销毁Lb
}

判断两个集合La Lb是否相等

bool  isequal( Linklist  La,   Linklist  Lb)  {  //判断集合La和Lb是否相等
	int La_len=ListLength(La); //求La表长
    int Lb_len=ListLength(Lb);//求Lb表长
	if(La_len!=Lb_len) {return FALSE;}
	Linklist Lc;
	InitList (Lc); //初始化Lc
	for(int i=1;i<=La_len;i++){  //建立La的副本Lc
		GetElem(La, i, ai);
		ListInsert(Lc,i,ai);
	}
  bool found=TRUE; //辅助变量found用来作为查找标志
	for(int k=1;k<=Lb_len && found; k++){
		GetElem(Lb, k, e);    //读取Lb中第k个元素e
		i=LocateElem(Lc,e);
		if(i==0) found=FALSE; //e在Lc中不存在,改标志
		else  ListDelete(Lc,i,e); //存在,Lc中删除e
	}	//for
  DestroyList(Lc);
  return found;
}

合并有序的算法实现:

void  MergeList ( List  La,   List  Lb,   List  &Lc)  {
       //将有序线性表La和Lb归并成有序线性表Lc
	int i = j = 1;
	int k=0;
	InitList (Lc); //初始化
	int La_len=ListLength(La);Lb_len=ListLength(Lb);//求表长
	while (i<=La_len && j<=Lb_len) { //La和Lb均非空
 		GetElem(La, i, ai); GetElem(Lb, j, bj);//读ai和bj
		if(ai<=bj){ListInsert(Lc, ++k, ai ); i++;}
		else {ListInsert(Lc, ++k, bj); j++;}
	}
	while(i<=La_len){ //La中剩余元素一一插入Lc
      GetElem(La,i++,ai); ListInsert(Lc, ++k, ai);}
	while(j<=Lb_len){ //Lb中剩余元素一一插入Lc
		GetElem(Lb,j++, bj); ListInsert(Lc, ++k,  bj);}
}

逆置单链表

第一种方法:

void ReverseLinkList1 ( LinkList  &L )   {
     // L是带头结点的单链表。用头插法逆置L
      p=L->next;                      //p指向a1
      L->next=NULL;              //剥离头结点
      while (p) {   q=p->next ;    //用辅助指针q“拽住”p的后继
                         p->next=L->next ; L->next=p ;
       //将当前待插入链表中的首结点*p插入L中,成为L的首结点
                         p=q ;  //p,q后移
       } // while
}

第二种

 //方法2:将所有结点的next指针逆转
void ReverseLinkList2 ( LinkList  &L )   {
// L是带头结点的单链表的头指针;p、q、r是三个辅助指针
//在扫描链表的过程中进行逆置操作
      if ( !L->next ) return;        //空表
      p=L->next;  q=p->next;  //原表中,*p为*q的前驱
      p->next=NULL;              //a1的next置空指针,剥离头结点
      while (q) {   r=q->next ;   //修改q->next之前,保存q->next到r
                         q->next=p ;   //逆置表中,*q为*p的前驱
                         p=q ; q=r ;    //参与扫描的指针都需后移
       }
       L->next=p;
}

循环链表

对循环链表的操作与普通单链表基本相同,只是判表空和判断表尾元素的条件有所不同:

        判断表尾:p->next == head
        判断表空:head->next == head

双向链表

typedef struct  DuLNode  {
       ElemType            data;
       struct  DuLNode    *prior;
       struct  DuLNode    *next;
}  DuLNode,  *DuLinkList;
DuLNode — 双向链表的结点类型
DuLinkList — 双向链表类型

约瑟夫环核心

//----------------约瑟夫环的实现-----------------------
int ImplementList(LinkList &L,int m)
{
    if(L==NULL)
    {
        printf("人数为空,出列结束");

        return FALSE;
    }
    LinkList p=L;
    printf("密码为: %d  ", m);

    while(p->next!=L) // 到第一个的前面
        p=p->next;
    for(int n=Listsize(L); n>0 ; n--)
    {
        for(int i=1; i<=m-1; i++){
            p=p->next;  // 一直往下,然后找到目标的前面;
            }
        m=p->next->data;
        printf(" 出列编号为:%d \n", p->next->number);
        printf("密码为: %d ", p->next->data);
        LinkList q=p->next;
        p->next=q->next;
        free(q);
    }
    return OK;
}
  • 13
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
【问题描述】 请设计一个链表类,实现链表初始化、插入、删除和打印操作。 节点的定义如下: typedef int elementType; typedef struct node { elementType data; node* next; } LList, *PList; 链表类的定义及要求如下: class linkedList { public: linkedList();//构造函数 virtual ~linkedList();//析构函数,注意要链表中所有节点的资源 void insert( int value );//警告:必须初始化才能使用! bool initiate();//初始化链表,使用new操作创建头结点。如果创建失败,则返回false,否则返回true bool isEmpty();//判断单链表是否为空 //删除单链表中第pos个元素结点,并将删除的节点的值存在value中。 //注意:如果链表为空、删除位置大于链表长度、以及删除位置为0的情况,需要终止删除并输出相应信息 bool remove( int pos, int& value ); void print();//顺序打印单链表,如果是单链表为空,则输出 Empty int Length();//返回单链表长度。如果是单链表为空,则返回-1 private: LList *head; int len; }; main函数: int main(int argc, char* argv[]) { linkedList L1; int n; int val; //初始化链表 if(!L1.initiate()) return 0; cin>>n;//输入链表中数据个数 for(int i=0; i<n; i++) //输入n个数,并插入链表 { cin>>val; L1.insert(val); } cout << "Origin Length:" << L1.Length() << endl;//输出链表长度 cout << "data:" ; L1.print();//打印链表 cin>>n;//输入需要删除的数据的位置 if (L1.remove(n,val)) { //删除位置n的数据,并将删除的数据值放在val中 cout<<"Delete the data at position("<<n<<"):"<<val<<endl; cout<< "New Length:" << L1.Length()<< endl;//输出链表长度 cout<< "data:" ; L1.print();//打印链表 } return 0; } 【输入形式】 输入包括3行。 第一行是链表元素个数n。第二行为n个元素的值。第三行为拟删除的数据位置。 【输出形式】 输出格式不固定。具体参见样例。 【样例输入1】 4 1 2 3 4 2 【样例输出1】 Origin Length:4 data:1 2 3 4 Delete the data at position(2):2 New Length:3 data:1 3 4 【样例输入2】 2 100 -1 3 【样例输出2】 Origin Length:2 data:100 -1 pos > len, failed 【样例输入3】 8 8 7 6 5 4 3 2 1 0 【样例输出3】 Origin Length:8 data:8 7 6 5 4 3 2 1 pos <= 0, failed

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值