链表用一组任意的存储单元存储线性表的数据元素,每个数据元素ai和指向后继的信息组成的存储映像称为结点,每个结点包含数据域和指针域。
目录
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.链表和顺序表的比较
链表占用的空间更多,但删减灵活性更强;顺序表在取值操作时效率更高。因此,事先确定大小,频繁取值操作时,因采用顺序表;频繁进行删减操作时,链表更适合。










