0
点赞
收藏
分享

微信扫一扫

线性表的链式表示

暮晨夜雪 2022-04-29 阅读 100

链表用一组任意的存储单元存储线性表的数据元素,每个数据元素ai和指向后继的信息组成的存储映像称为结点,每个结点包含数据域指针域

目录

1.老师的代码

        1.1结构体

        1.2初始化

        1.3打印链表

        1.4链表尾部加入元素

        1.5在指定位置后加入元素

        1.6删除结点

        1.7测试函数

        1.8打印地址函数

        1.9运行结果

2.自己的代码

        2.1在链表第一个元素加入元素

        2.2按位置查找函数,返回data

        2.3按值查找函数,返回指针

        2.4清空链表

        2.5test函数

        2.6完整代码及运行结果

3.链表和顺序表的比较

1.老师的代码

       1.1 结构体



typedef struct LinkNode{
    char data;
    struct LinkNode *next;
}LNode,*LinkList,*NodePtr;

        1.2初始化


LinkList initLinkList(){
    NodePtr tempHeader=(NodePtr)malloc(sizeof(LNode));
    tempHeader->data='\0';
    tempHeader->next=NULL;
    return tempHeader;
}

        1.3打印链表


void printList(NodePtr paraHeader){
    NodePtr p=paraHeader->next;
    while(p!=NULL){
        printf("%c",p->data);
        p=p->next;
    }
    printf("\r\n");
}

        1.4链表尾部加入元素


void appendElement(NodePtr paraHeader,char paraChar){
    NodePtr p,q;
    
    q=(NodePtr)malloc(sizeof(LNode));
    q->data=paraChar;
    q->next=NULL;
    
    p=paraHeader;
    while(p->next!=NULL){
        p=p->next;
    }
    
    p->next=q;
}

第一步:p指向头结点,q指向待加入结点

 

第二步:p指向next为NULL的结点

 

第三步:p指向的结点的next指向q指向的结点,即把p,q分别指向的结点相连

 

        1.5在指定位置后加入元素


void insertElement(NodePtr paraHeader,char paraChar,int paraPosition){
    NodePtr p,q;
    
    p=paraHeader;
    for(int i=0;i<paraPosition;i++){
        p=p->next;
        if(p==NULL){
            printf("The position %d is beyond the scope of the list.",paraPosition);
            return;
        }
    }

    q=(NodePtr)malloc(sizeof(LNode));
    q->data=paraChar;

    printf("linking\r\n");
    q->next=p->next;
    p->next=q;
}

        第一步:q指向待加入结点,p指向头节点

 

        第二步:通过循环,使p指向指定位置结点

 

        第三步:,待加入结点next指向p后一个结点,p指向的结点的next指向待加入结点

        1.6删除结点

void deleteElement(NodePtr paraHeader,char paraChar){
    NodePtr p,q;
    p=paraHeader;
    int i=0;
    while((p->next!=NULL)&&(p->next->data!=paraChar)){
    	//printf("now=%d\n",i);
    	i++;
    	//printf("2\n");
        p=p->next;
        //printf("3\n") ;
    }
    
    //printf("4\n");
    if(p->next==NULL){
        printf("Cannot delete %c\r\n",paraChar);
        return;
    }

    q=p->next;
    p->next=p->next->next;
    free(q);
}

           第一步:p指向头结点

 

           第二步:通过循环,使p指向待删除结点前一个结点,q指向待删除结点

 

           第三步:使p指向的结点的next指向待删除结点后一个结点(这里为NULL),并释放q指向的区域

 

        1.7测试函数


void appendInsertDeleteTest(){
    LinkList tempList=initLinkList();
    printList(tempList);

    appendElement(tempList,'H');
    appendElement(tempList,'e');
    appendElement(tempList,'l');
    appendElement(tempList,'l');
    appendElement(tempList,'o');
    appendElement(tempList,'!');
    printList(tempList);
    
    deleteElement(tempList,'e');
    deleteElement(tempList,'a');
    deleteElement(tempList,'o');
    printList(tempList);
    
    insertElement(tempList,'o',1);
    printList(tempList);
}

        1.8打印地址函数


void basicAddressTest(){
    LNode tempNode1,tempNode2;
    
    tempNode1.data=4;
    tempNode1.next=NULL;
    
    tempNode2.data=6;
    tempNode2.next=NULL;

    printf("The fristnode:%d,%d,%d\r\n",&tempNode1,&tempNode1.data,&tempNode1.next);
    printf("The secondnode:%d,%d,%d\r\n",&tempNode2,&tempNode2.data,&tempNode2.next);
    
    tempNode1.next=&tempNode2;
}

        1.9运行结果如图

2. 自己的代码

        2.1在链表第一个位置加入元素


void appendhead(node pH,char pC){
	node p,q;
	
	p=(node)malloc(sizeof(Lnode));
	p->data=pC;
	p->next=NULL;
	
	q=pH;
	p->next=q->next;
	q->next=p;
}

 第一步:p指向头结点,q指向待加入结点

 

第二步:使待加入结点的next指向头结点的next

 第三步:头结点的next指向待加入结点

         2.2按位置查找函数,返回data


char get(node pH,int pPos){
	if(pPos<0){
		printf("ERROR! 请输入一个大于零的数!\n");
		return '\0';
	} //判断pPos是否合法
	
	node p=pH;
	int i;

    //循环至所求位置
	for(i=0;i<pPos;++i){
		p=p->next;
		if(p==NULL){
			printf("ERROR! 超过限度!\n");    //超过链表长度,输出原因,退出
			return'\0';
		}	
	}
	
	return p->data;    //合法,返回data
}

       2.3 按值查找函数,返回指针


node locate(node pH,char pC){
	node p=pH;

    //循环比对元素值
	while((p->next!=NULL)&&(p->next->data!=pC)){
		p=p->next;		
	}
	
	p=p->next;

    //遍历完整个链表则证明没有找到
	if(p==NULL){
			printf("ERROR! 未找到!\n");
			return NULL;    //返回NULL
	}
		
	return p;
} 

        2.4清空链表


void destroy(node pH){
	node p=pH;
	node q=pH->next;
	
    //循环释放空间
	while(q!=NULL){
		free(p);
		p=q;
		q=q->next;
		//printf("YES\n");
	}
	free(p);
	printf("DESTROY END!");
}

        2.5test函数


void Test(){

	Link t=init();    //初始化
	printf("初始化 :");
	printL(t);
	
    //append函数测试
	append(t,'c');
	append(t,'s') ;
	append(t,'d');
	append(t,'n');
	printf("尾部添加元素 :");
	printL(t);

    //delete函数测试
	deleteL(t,'s');
	deleteL(t,'a');    //测试没有找到的情况
	deleteL(t,'d');
	printf("删除元素 :");
	printL(t);
	
    //inserttail函数测试
	inserttail(t,'w',1);
	inserttail(t,'o',2);
	inserttail(t,'p',8);    //超过链表长度测试
	printf("在指定元素后加入 :");
	printL(t);
	
    //appendhead函数测试
	appendhead(t,'b');
	appendhead(t,'l');
	printf("头插法 :");
	printL(t);
	
    //GET测试
	char bb=get(t,2);
	printf("GET : %c\n",bb);

	char cc=get(t,7);    //未找到元素的情况
	printf("GET : %c\n",cc);
	
    //locate测试
	node tt=locate(t,'b');
	printf("LOCATE : %ld\n",tt);

	node mm=locate(t,'q');    //未找到元素测试
	printf("LOCATE : %ld\n",mm);
	
	destroy(t);    //释放内存
	
}

        2.6完整代码及运行结果

#include <stdio.h>
#include <malloc.h>

typedef struct Linknode{
	char data;
	struct Linknode *next;
}Lnode,*Link,*node;


Link init(){
	node tHeared=(node)malloc(sizeof(Lnode));
	tHeared->data='\0';
	tHeared->next=NULL;
	
	return tHeared;
}


void printL(node pH){
	node pr=pH->next;
	
	while(pr!=NULL){
		printf("%c",pr->data);
		pr=pr->next;
	}
	printf("\r\n");
}
	

void append(node pH,char pC){
	node p,q;
	
	p=(node)malloc(sizeof(Lnode));
	p->data=pC;
	p->next=NULL;
	
	q=pH;
	while(q->next!=NULL)
		q=q->next;
	
	q->next=p;
}

void deleteL(node pH,char pC){
	node p,q;
	
	p=pH;
	while((p->next!=NULL)&&(p->next->data!=pC))
		p=p->next;
	
	if(p->next==NULL){
		printf("ERROR! 未找到\n");
		return; 
	}
	
	q=p->next;
	p->next=p->next->next;
	free(q);	
}

void inserttail(node pH,char pC,int pPos){
	node p,q;
	
	if(pPos<0){
		printf("ERROR!请输入一个大于零的数!\n");
	}
	p=(node)malloc(sizeof(Lnode));
	p->data=pC;
	p->next=NULL;
	
	int i; q=pH;
	for(i=0;i<pPos;++i){
		q=q->next;
		if(q==NULL){
			printf("ERROR! 超过最大限度!\n");
			return;
		}
	}
	
	p->next=q->next;
	q->next=p;
}

void appendhead(node pH,char pC){
	node p,q;
	
	p=(node)malloc(sizeof(Lnode));
	p->data=pC;
	p->next=NULL;
	
	q=pH;
	p->next=q->next;
	q->next=p;
}

char get(node pH,int pPos){
	if(pPos<0){
		printf("ERROR! 请输入一个大于零的数!\n");
		return '\0';
	} //判断pPos是否合法
	
	node p=pH;
	int i;

    //循环至所求位置
	for(i=0;i<pPos;++i){
		p=p->next;
		if(p==NULL){
			printf("ERROR! 超过限度!\n");    //超过链表长度,输出原因,退出
			return'\0';
		}	
	}
	
	return p->data;    //合法,返回data
}



node locate(node pH,char pC){
	node p=pH;

    //循环比对元素值
	while((p->next!=NULL)&&(p->next->data!=pC)){
		p=p->next;		
	}
	
	p=p->next;

    //遍历完整个链表则证明没有找到
	if(p==NULL){
			printf("ERROR! 未找到!\n");
			return NULL;    //返回NULL
	}
		
	return p;
} 


void destroy(node pH){
	node p=pH;
	node q=pH->next;
	
    //循环释放空间
	while(q!=NULL){
		free(p);
		p=q;
		q=q->next;
		//printf("YES\n");
	}
	free(p);
	printf("DESTROY END!");
}

void Test(){

	Link t=init();    //初始化
	printf("初始化 :");
	printL(t);
	
    //append函数测试
	append(t,'c');
	append(t,'s') ;
	append(t,'d');
	append(t,'n');
	printf("尾部添加元素 :");
	printL(t);

    //delete函数测试
	deleteL(t,'s');
	deleteL(t,'a');    //测试没有找到的情况
	deleteL(t,'d');
	printf("删除元素 :");
	printL(t);
	
    //inserttail函数测试
	inserttail(t,'w',1);
	inserttail(t,'o',2);
	inserttail(t,'p',8);    //超过链表长度测试
	printf("在指定元素后加入 :");
	printL(t);
	
    //appendhead函数测试
	appendhead(t,'b');
	appendhead(t,'l');
	printf("头插法 :");
	printL(t);
	
    //GET测试
	char bb=get(t,2);
	printf("GET : %c\n",bb);

	char cc=get(t,7);    //未找到元素的情况
	printf("GET : %c\n",cc);
	
    //locate测试
	node tt=locate(t,'b');
	printf("LOCATE : %ld\n",tt);

	node mm=locate(t,'q');    //未找到元素测试
	printf("LOCATE : %ld\n",mm);
	
	destroy(t);    //释放内存
	
}


void main(){
	Test();
}

        本地运行结果如图

3.链表和顺序表的比较

 链表占用的空间更多,但删减灵活性更强;顺序表在取值操作时效率更高。因此,事先确定大小,频繁取值操作时,因采用顺序表;频繁进行删减操作时,链表更适合。

 

举报

相关推荐

0 条评论