链式表: 单向链表 节点:数据元素+指针域(下一个Node的内存)
main.c
#include <stdio.h>
#include <stdlib.h>
#include "singlelinketlist.h"
void print(int num){
printf("%d ",num);
}
void showMenu(void){
printf("***单向链表功能测试*****\n");
printf("** 1.插入一个元素 \n");
printf("** 2.查找 \n");
printf("** 3.链表为空判断 \n");
printf("** 4.元素个数 \n");
printf("** 5.遍历 \n");
printf("** 6.清空所有元素 \n");
printf("** 7.在表头插入 \n");
printf("** 8.在末尾插入 \n");
printf("** 9.删除 \n");
printf("** 10.删除第一个元素 \n");
printf("** 11.删除最后一个元素 \n");
printf("** 12.获取指定位置的元素 \n");
printf("** 13.第一个元素 \n");
printf("** 14.最后一个元素 \n");
printf("** 15.逆序 \n");
printf("** 16.快速插入数据\n");
printf("** 17.1,n,2,n-1,3,n-2,4,...\n");
printf("** 18.按指定元素个数逆序 \n");
printf("** 0.销毁 \n");
printf(">>>>>");
}
void find(SLinketList list){
printf("请输入要查找的值:");
ETYPE key = 0;
scanf("%d",&key);
int ret = slinket_list_find(list,&key);
if(ret == -1){
printf("没有该元素!\n");
}else{
printf("该元素第一次出现在:%u\n",ret);
}
}
void insert_data(SLinketList list){
printf("请输入插入元素的个数:");
size_t num = 0;
scanf("%u",&num);
size_t i;
for(i=0;i<num;i++){
slinket_list_insert_back(list,i+1);
}
slinket_list_travel(list,print);
printf("\n");
}
void reverse(SLinketList list){
size_t cnt = 0;
printf("请输入按几个元素逆序:");
scanf("%u",&cnt);
slinket_list_reverse_by_count(list,cnt);
slinket_list_travel(list,print);
printf("\n");
}
void add(SLinketList list){
printf("请输入位置[0-%u]:",slinket_list_size(list));
size_t pos = 0;
scanf("%u",&pos);
printf("请输入要插入的元素:");
ETYPE elem;
scanf("%d",&elem);
int ret = slinket_list_insert(list,pos,elem);
if(ret == 0){
printf("插入成功!\n");
}else{
printf("插入失败!\n");
}
}
void test_single_linket_list(void){
SLinketList list = slinket_list_create();
ETYPE data = 0;
size_t pos = 0;
int ret = 0;
while(true){
showMenu();
int opt = 0;
scanf("%d",&opt);
switch(opt){
case 1:
add(list);
break;
case 2:
find(list);
break;
case 3:
slinket_list_is_empty(list)?printf("空空如也!\n"):printf("海纳百川\n");
break;
case 4:
printf("元素个数:%u\n",slinket_list_size(list));
break;
case 5:
slinket_list_travel(list,print);
printf("\n");
break;
case 6:
slinket_list_clear(list);
break;
case 7:
printf("请输入要插入元素:");
scanf("%d",&data);
ret = slinket_list_insert_front(list,data);
if(ret == 0){
printf("插入成功!\n");
}else{
printf("插入失败!\n");
}
break;
case 8:
printf("请输入要插入的元素:");
scanf("%d",&data);
ret = slinket_list_insert_back(list,data);
if(ret == 0){
printf("插入成功!\n");
}else{
printf("插入失败!\n");
}
break;
case 9:
printf("请输入要删除的位置:");
scanf("%u",&pos);
ret = slinket_list_delete(list,pos,&data);
if(ret == 0){
printf("删除的结点元素为:%d\n",data);
}else{
printf("删除失败!\n");
}
break;
case 10:
ret = slinket_list_delete_front(list,&data);
if(ret == 0){
printf("删除的结点元素为:%d\n",data);
}else{
printf("删除失败!\n");
}
break;
case 11:
ret = slinket_list_delete_back(list,&data);
if(ret == 0){
printf("删除的结点元素为:%d\n",data);
}else{
printf("删除失败!\n");
}
break;
case 12:
printf("请输入要获得结点的位置[0-%u)",slinket_list_size(list));
scanf("%u",&pos);
ret = slinket_list_get(list,pos,&data);
if(ret == 0){
printf("%u位置结点的元素为%d\n",pos,data);
}else{
printf("获取出错!\n");
}
break;
case 13:
ret = slinket_list_get_front(list,&data);
if(ret == 0){
printf("第一个位置结点的元素为%d\n",data);
}else{
printf("获取出错!\n");
}
break;
case 14:
ret = slinket_list_get_back(list,&data);
if(ret == 0){
printf("最后一个位置结点的元素为%d\n",data);
}else{
printf("获取出错!\n");
}
break;
case 15:
slinket_list_reverse(list);
slinket_list_travel(list,print);
printf("\n");
break;
case 16:
insert_data(list);
break;
case 17:
slinket_list_reset_seq(list);
slinket_list_travel(list,print);
printf("\n");
break;
case 18:
reverse(list);
break;
case 0:
slinket_list_destroy(list);
return;
}
}
}
int main(int argc, char *argv[]) {
test_single_linket_list();
return 0;
}
slinketlist.h
#ifndef SINGLE_LINKET_LIST_H__
#define SINGLE_LINKET_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ETYPE;
typedef struct Node{
ETYPE elem;
struct Node *next;
}SNode,*SLinketList;
#define NODESIZE sizeof(struct Node)
SLinketList slinket_list_create(void);
bool slinket_list_is_empty(SLinketList head);
size_t slinket_list_size(SLinketList head);
int slinket_list_insert(SLinketList head,size_t pos,ETYPE elem);
int slinket_list_insert_front(SLinketList head,ETYPE elem);
int slinket_list_insert_back(SLinketList head,ETYPE elem);
int slinket_list_delete(SLinketList head,size_t pos,ETYPE *pelem);
int slinket_list_delete_front(SLinketList head,ETYPE *pelem);
int slinket_list_delete_back(SLinketList head,ETYPE *pelem);
int slinket_list_get(SLinketList head,size_t pos,ETYPE *pelem);
int slinket_list_get_front(SLinketList head,ETYPE *pelem);
int slinket_list_get_back(SLinketList head,ETYPE *pelem);
int slinket_list_find(SLinketList head,ETYPE *pelem);
void slinket_list_travel(SLinketList head,void (*travel)(int));
void slinket_list_clear(SLinketList head);
void slinket_list_destroy(SLinketList head);
void slinket_list_reverse(SLinketList head);
int slinket_list_get_last(SLinketList head,size_t pos,ETYPE *pelem);
void slinket_list_reset_seq(SLinketList head);
void slinket_list_reverse_by_count(SLinketList head,size_t count);
#endif
slinketlist.c
#include "singlelinketlist.h"
SLinketList slinket_list_create(void){
struct Node* head = (struct Node*)malloc(NODESIZE);
if(head==NULL){
return NULL;
}
head->next = NULL;
return head;
}
bool slinket_list_is_empty(SLinketList head){
return head->next == NULL;
}
size_t slinket_list_size(SLinketList head){
size_t size = 0;
struct Node *node = head->next;
while(node != NULL){
size++;
node = node->next;
}
return size;
}
static struct Node * slinket_list_get_prev_node(SLinketList head,size_t pos){
struct Node *node = head;
size_t i;
for(i=0;node!=NULL&&i<pos;i++){
node = node->next;
}
return node;
}
int slinket_list_insert(SLinketList head,size_t pos,ETYPE elem){
struct Node *prev = slinket_list_get_prev_node(head,pos);
if(prev == NULL){
return -1;
}
struct Node *node = (struct Node *)malloc(NODESIZE);
if(node==NULL){
return -2;
}
node->elem = elem;
node->next = prev->next;
prev->next = node;
return 0;
}
int slinket_list_insert_front(SLinketList head,ETYPE elem){
struct Node *node = (struct Node *)malloc(NODESIZE);
if(node==NULL){
return -1;
}
node->elem = elem;
node->next = head->next;
head->next = node;
return 0;
}
int slinket_list_insert_back(SLinketList head,ETYPE elem){
struct Node *last = head;
while(last->next!=NULL){
last = last->next;
}
struct Node *node = (struct Node *)malloc(NODESIZE);
node->elem = elem;
node->next = NULL;
last->next = node;
return 0;
}
int slinket_list_delete(SLinketList head,size_t pos,ETYPE *pelem){
struct Node *prev = slinket_list_get_prev_node(head,pos);
if(prev == NULL || prev->next == NULL){
return -1;
}
struct Node *curr = prev->next;
prev->next = curr->next;
*pelem = curr->elem;
free(curr);
return 0;
}
int slinket_list_delete_front(SLinketList head,ETYPE *pelem){
if(head->next == NULL){
return -1;
}
*pelem = head->next->elem;
struct Node *first = head->next;
head->next = first->next;
free(first);
return 0;
}
int slinket_list_delete_back(SLinketList head,ETYPE *pelem){
if(head->next == NULL){
return -1;
}
struct Node *lastSec = head;
while(lastSec->next->next != NULL){
lastSec = lastSec->next;
}
*pelem = lastSec->next->elem;
free(lastSec->next);
lastSec->next = NULL;
return 0;
}
int slinket_list_get(SLinketList head,size_t pos,ETYPE *pelem){
struct Node *node = slinket_list_get_prev_node(head,pos+1);
if(node == NULL){
return -1;
}
*pelem = node->elem;
return 0;
}
int slinket_list_get_front(SLinketList head,ETYPE *pelem){
if(head->next == NULL){
return -1;
}
*pelem = head->next->elem;
return 0;
}
int slinket_list_get_back(SLinketList head,ETYPE *pelem){
if(head->next == NULL){
return -1;
}
struct Node *last = head->next;
while(last->next != NULL){
last = last->next;
}
*pelem = last->elem;
return 0;
}
int slinket_list_find(SLinketList head,ETYPE *pelem){
struct Node *node = head->next;
size_t i;
for(i=0;node!=NULL;node=node->next,i++){
if(node->elem == *pelem){
return i;
}
}
return -1;
}
void slinket_list_travel(SLinketList head,void (*travel)(int)){
struct Node *node = head->next;
while(node!=NULL){
travel(node->elem);
node = node->next;
}
}
void slinket_list_clear(SLinketList head){
struct Node *node,*next;
for(node=head->next;node!=NULL;node=next){
next = node->next;
free(node);
}
head->next = NULL;
}
void slinket_list_destroy(SLinketList head){
slinket_list_clear(head);
free(head);
}
void slinket_list_reverse(SLinketList head){
if(head->next == NULL || head->next->next == NULL){
return;
}
struct Node *prev = NULL;
struct Node *curr = head->next;
struct Node *next = NULL;
while(curr!=NULL){
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head->next = prev;
}
int slinket_list_get_last(SLinketList head,size_t pos,ETYPE *pelem){
struct Node *front = head->next;
struct Node *back = head->next;
size_t i;
for(i=1;front!=NULL&&i<pos;i++){
front = front->next;
}
if(front == NULL){
return -1;
}
while(front->next!=NULL){
front = front->next;
back = back->next;
}
*pelem = back->elem;
return 0;
}
void slinket_list_reset_seq(SLinketList head){
size_t size = slinket_list_size(head);
if(size<=2)
return;
size_t i;
struct Node *node = head->next;
for(i=0;i<size/2;i++){
node = node->next;
}
slinket_list_reverse(node);
struct Node *front = node->next, *back = head->next;
node->next = NULL;
node = head;
bool flag = true;
while(front!=NULL && back!=NULL){
node->next = back;
back = back->next;
node = node->next;
node->next = front;
front = front->next;
node = node->next;
}
node->next = back;
}
void slinket_list_reverse_by_count(SLinketList head,size_t count){
struct Node *prev = NULL;
struct Node *curr = head->next;
struct Node *next = NULL;
struct Node *last = head;
struct Node *first = NULL;
size_t i=0;
while(curr != NULL){
first = curr;
for(i=0;curr!=NULL&&i<count;i++){
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
last->next = prev;
last = first;
}
last->next = NULL;
}
//常考
//单向链表逆序
void slinket_list_reverse(SLinketList head){
if(head->next==NULL || head->next->next==NULL){
return; //没有节点或者只有一个节点,不需要做任何事情
}
struct Node *prev=NULL;
struct Node *curr=head->next;
struct Node *next=NULL;
while(curr!=NULL){
next = curr->next;//保存当前节点的下一个节点,因为下一步这个信息就被替换了
curr->next=prev;//逆转当前节点,指向原来的前节点
prev=curr;
curr=next;
}
head->next=prev;//curr==NULL的时候,prev就是最后一个的位置
}
//获取倒数第n个元素
int slinket_list_get_last(SLinketList head,size_t pos,ETYPE *pelem){
struct Node *front=head->next;
struct Node *back=head->next;
size_t i;
for(i=1;front!=NULL && i<pos;i++){
front=front->next; //先让front先走pos-1步
}
if(front==NULL){
return -1;
}
while(front=NULL){
front=front->next;
back=back->next;
}//front循环结束指向最后一个的下一个即NULL
*pelem=back->elem;
return 0;
}
void slinket_list_reset_seq(SLinketList head);
按指定元素个数逆序 a1 a2
void slinket_list_reverse_by_count(SLinketList head,size_t count)
万能模板 main.c
#include <stdio.h>
#include <stdlib.h>
#include "slinkedlist.h"
typedef struct Stu{
int no;
char name[40];
int score[3];
}Stu;
int comp_no(const void *v1,const void *v2){
const struct Stu *ps1 = (const struct Stu *)v1;
const struct Stu *ps2 = (const struct Stu *)v2;
return ps1->no - ps2->no;
}
int comp_name(const void *v1,const void *v2){
const struct Stu *ps1 = (const struct Stu *)v1;
const struct Stu *ps2 = (const struct Stu *)v2;
return strcmp(ps1->name,ps2->name);
}
void show_stu(const void *pv){
const Stu *pstu = (const Stu *)pv;
printf("%d %s %d %d %d\n",
pstu->no,pstu->name,pstu->score[0],pstu->score[1],pstu->score[2]);
}
int main(int argc, char *argv[]) {
SLinkedList list = slinked_list_create(sizeof(struct Stu));
struct Stu stus[]={
{110,"余华康",{54,67,40}},
{120,"杨承杰",{78,67,90}},
{119,"王涵",{60,83,100}},
{127,"陈圣泽",{67,87,99}},
{101,"周涵",{80,82,90}}
};
size_t i,len = sizeof(stus)/sizeof(stus[0]);
for(i=0;i<len;i++){
slinked_list_insert(list,i/2,(const void*)&stus[i]);
}
printf("size:%u\n",slinked_list_size(list));
struct Stu s ={100,"李子璇",{87,70,60}};
slinked_list_insert(list,3,&s);
printf("size:%u\n",slinked_list_size(list));
slinked_list_travel(list,show_stu);
slinked_list_delete(list,3,&s);
show_stu(&s);
printf("------------\n");
slinked_list_travel(list,show_stu);
struct Stu sf = {110};
struct Stu *ps = slinked_list_find(list,&sf,comp_no);
if(ps == NULL){
printf("没有找到!\n");
}else{
printf("找到了:");
show_stu(ps);
}
strcpy(sf.name,"王涵");
ps = slinked_list_find(list,&sf,comp_name);
if(ps == NULL){
printf("没有找到!\n");
}else{
printf("找到了:");
show_stu(ps);
}
slinked_list_destroy(list);
return 0;
}
.h
#ifndef SLINKED_LIST_H__
#define SLINKED_LIST_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node{
void *pelem;
struct Node *next;
}SNode;
typedef struct SLinkedList{
struct Node *head;
size_t elemSize;
size_t size;
}*SLinkedList;
#define NODESIZE sizeof(struct Node)
#define LISTSIZE sizeof(struct SLinkedList)
SLinkedList slinked_list_create(size_t elemSize);
bool slinked_list_empty(SLinkedList list);
size_t slinked_list_size(SLinkedList list);
void slinked_list_clear(SLinkedList list);
void slinked_list_destroy(SLinkedList list);
void slinked_list_travel(SLinkedList list,void (*travel)(const void *));
int slinked_list_insert(SLinkedList list,size_t pos,const void *pelem);
int slinked_list_delete(SLinkedList list,size_t pos,void *pelem);
int slinked_list_get(SLinkedList list,size_t pos,void *pelem);
void *slinked_list_index(SLinkedList list,size_t pos);
void *slinked_list_find(SLinkedList list,const void *key,int (*cmp)(const void*,const void*));
#endif
.c
#include "slinkedlist.h"
SLinkedList slinked_list_create(size_t elemSize){
SLinkedList list = (SLinkedList)malloc(LISTSIZE);
if(list == NULL){
return NULL;
}
list->head = (struct Node*)malloc(NODESIZE);
if(list->head == NULL){
free(list);
return NULL;
}
list->head->next = NULL;
list->elemSize = elemSize;
list->size = 0;
return list;
}
bool slinked_list_empty(SLinkedList list){
return list->size == 0;
}
size_t slinked_list_size(SLinkedList list){
return list->size;
}
void slinked_list_clear(SLinkedList list){
struct Node *node = list->head->next;
struct Node *next = NULL;
while(node != NULL){
next = node->next;
free(node->pelem);
free(node);
node = next;
}
list->head = NULL;
}
void slinked_list_destroy(SLinkedList list){
slinked_list_clear(list);
free(list->head);
free(list);
}
void slinked_list_travel(SLinkedList list,void (*travel)(const void *)){
struct Node *node = list->head->next;
for(;node!=NULL;node = node->next){
travel(node->pelem);
}
}
static struct Node *slinked_list_get_prev_node(SLinkedList list,size_t pos){
struct Node *node = list->head;
size_t i;
for(i=0;node!=NULL&&i<pos;i++){
node = node->next;
}
return node;
}
int slinked_list_insert(SLinkedList list,size_t pos,const void *pelem){
struct Node *prev = slinked_list_get_prev_node(list,pos);
if(prev == NULL){
return -1;
}
struct Node *node = (struct Node*)malloc(NODESIZE);
if(node == NULL){
return -2;
}
node->pelem = malloc(list->elemSize);
if(node->pelem == NULL){
free(node);
return -3;
}
memcpy(node->pelem,pelem,list->elemSize);
node->next = prev->next;
prev->next = node;
list->size++;
return 0;
}
int slinked_list_delete(SLinkedList list,size_t pos,void *pelem){
struct Node *prev = slinked_list_get_prev_node(list,pos);
if(prev==NULL||prev->next==NULL){
return -1;
}
struct Node *curr = prev->next;
memcpy(pelem,curr->pelem,list->elemSize);
prev->next = curr->next;
--list->size;
free(curr->pelem);
free(curr);
return 0;
}
int slinked_list_get(SLinkedList list,size_t pos,void *pelem){
struct Node *curr = slinked_list_get_prev_node(list,pos+1);
if(curr == NULL){
return -1;
}
memcpy(pelem,curr->pelem,list->elemSize);
return 0;
}
void *slinked_list_index(SLinkedList list,size_t pos){
struct Node *node = slinked_list_get_prev_node(list,pos);
if(node == NULL){
return NULL;
}
return node->pelem;
}
void *slinked_list_find(SLinkedList list,const void *key,int (*cmp)(const void*,const void*)){
struct Node *node = list->head->next;
for(;node!=NULL;node = node->next){
if(cmp(key,node->pelem)==0){
return node->pelem;
}
}
return NULL;
}
|