- DSA 使用 C 教程
- 使用 C 的 DSA - 主页
- 使用 C 语言的 DSA - 概述
- 使用 C 语言的 DSA - 环境
- 使用 C 算法的 DSA
- 使用 C 的 DSA - 概念
- 使用 C 数组的 DSA
- 使用 C 链表的 DSA
- 使用 C 的 DSA - 双向链表
- 使用 C 的 DSA - 循环链表
- 使用 C 的 DSA - 堆栈内存溢出
- 使用 C 的 DSA - 解析表达式
- 使用 C 队列的 DSA
- 使用 C 的 DSA - 优先级队列
- 使用 C 树的 DSA
- 使用 C 哈希表的 DSA
- 使用 C 堆的 DSA
- 使用 C - Graph 的 DSA
- 使用 C 搜索技术的 DSA
- 使用 C 排序技术的 DSA
- 使用 C 的 DSA - 递归
- 使用 C 语言的 DSA 有用资源
- 使用 C 的 DSA - 快速指南
- 使用 C 的 DSA - 有用资源
- 使用 C 的 DSA - 讨论
使用 C 链表的 DSA
概述
链接列表是包含项目的链接序列。每个链接都包含到另一个链接的连接。链表是继数组之后第二常用的数据结构。以下是理解链表概念的重要术语。
链接- 链表的每个链接都可以存储称为元素的数据。
Next - 链接列表的每个链接都包含一个指向下一个链接的链接,称为“Next”。
LinkedList - LinkedList 包含指向名为 First 的第一个链接的连接链接。
链表表示
根据上图所示,以下是需要考虑的要点。
LinkedList 包含一个名为first 的链接元素。
每个链接携带一个数据字段和一个接下来调用的链接字段。
每个链接都使用其下一个链接与其下一个链接进行链接。
Last Link 带有一个为 null 的 Link 来标记列表的结尾。
链表的类型
以下是链表的各种风格。
简单链接列表- 项目导航仅向前。
双向链表- 项目可以向前和向后导航。
循环链表- 最后一项包含第一个元素作为下一个元素的链接,第一个元素包含到最后一个元素作为上一个元素的链接。
基本操作
以下是列表支持的基本操作。
插入- 在列表的开头添加一个元素。
删除- 删除列表开头的元素。
显示- 显示完整列表。
搜索- 使用给定键搜索元素。
删除- 使用给定键删除元素。
插入操作
插入是一个三步过程 -
使用提供的数据创建新链接。
将新链接指向旧的第一个链接。
将第一个链接指向此新链接。
//insert link at the first location
void insertFirst(int key, int data){
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
删除操作
删除是一个两步过程 -
获取第一个链接指向的链接作为临时链接。
将第一个链接指向临时链接的下一个链接。
//delete first item
struct node* deleteFirst(){
//save reference to first link
struct node *tempLink = head;
//mark next to first link as first
head = head->next;
//return the deleted link
return tempLink;
}
导航操作
导航是一个递归步骤过程,是搜索、删除等许多操作的基础。 -
获取第一个链接指向的链接作为当前链接。
检查当前链接是否不为空并显示它。
将当前链接指向当前链接的下一个链接并移至上述步骤。
注意 -
//display the list
void printList(){
struct node *ptr = head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL){
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
}
printf(" ]");
}
高级操作
以下是为列表指定的高级操作。
排序- 根据特定顺序对列表进行排序。
反转- 反转链表。
排序操作
我们使用冒泡排序来对列表进行排序。
void sort(){
int i, j, k, tempKey, tempData ;
struct node *current;
struct node *next;
int size = length();
k = size ;
for ( i = 0 ; i < size - 1 ; i++, k-- ) {
current = head ;
next = head->next ;
for ( j = 1 ; j < k ; j++ ) {
if ( current->data > next->data ) {
tempData = current->data ;
current->data = next->data;
next->data = tempData ;
tempKey = current->key;
current->key = next->key;
next->key = tempKey;
}
current = current->next;
next = next->next;
}
}
}
反向操作
以下代码演示了反转单个链表。
void reverse(struct node** head_ref) {
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
例子
LinkedListDemo.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
int data;
int key;
struct node *next;
};
struct node *head = NULL;
struct node *current = NULL;
//display the list
void printList(){
struct node *ptr = head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL){
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
}
printf(" ]");
}
//insert link at the first location
void insertFirst(int key, int data){
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
//delete first item
struct node* deleteFirst(){
//save reference to first link
struct node *tempLink = head;
//mark next to first link as first
head = head->next;
//return the deleted link
return tempLink;
}
//is list empty
bool isEmpty(){
return head == NULL;
}
int length(){
int length = 0;
struct node *current;
for(current = head; current!=NULL;
current = current->next){
length++;
}
return length;
}
//find a link with given key
struct node* find(int key){
//start from the first link
struct node* current = head;
//if list is empty
if(head == NULL){
return NULL;
}
//navigate through list
while(current->key != key){
//if it is last node
if(current->next == NULL){
return NULL;
} else {
//go to next link
current = current->next;
}
}
//if data found, return the current Link
return current;
}
//delete a link with given key
struct node* delete(int key){
//start from the first link
struct node* current = head;
struct node* previous = NULL;
//if list is empty
if(head == NULL){
return NULL;
}
//navigate through list
while(current->key != key){
//if it is last node
if(current->next == NULL){
return NULL;
} else {
//store reference to current link
previous = current;
//move to next link
current = current->next;
}
}
//found a match, update the link
if(current == head) {
//change first to point to next link
head = head->next;
} else {
//bypass the current link
previous->next = current->next;
}
return current;
}
void sort(){
int i, j, k, tempKey, tempData ;
struct node *current;
struct node *next;
int size = length();
k = size ;
for ( i = 0 ; i < size - 1 ; i++, k-- ) {
current = head ;
next = head->next ;
for ( j = 1 ; j < k ; j++ ) {
if ( current->data > next->data ) {
tempData = current->data ;
current->data = next->data;
next->data = tempData ;
tempKey = current->key;
current->key = next->key;
next->key = tempKey;
}
current = current->next;
next = next->next;
}
}
}
void reverse(struct node** head_ref) {
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
main() {
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
printf("Original List: ");
//print list
printList();
while(!isEmpty()){
struct node *temp = deleteFirst();
printf("\nDeleted value:");
printf("(%d,%d) ",temp->key,temp->data);
}
printf("\nList after deleting all items: ");
printList();
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
printf("\nRestored List: ");
printList();
printf("\n");
struct node *foundLink = find(4);
if(foundLink != NULL){
printf("Element found: ");
printf("(%d,%d) ",foundLink->key,foundLink->data);
printf("\n");
} else {
printf("Element not found.");
}
delete(4);
printf("List after deleting an item: ");
printList();
printf("\n");
foundLink = find(4);
if(foundLink != NULL){
printf("Element found: ");
printf("(%d,%d) ",foundLink->key,foundLink->data);
printf("\n");
} else {
printf("Element not found.");
}
printf("\n");
sort();
printf("List after sorting the data: ");
printList();
reverse(&head);
printf("\nList after reversing the data: ");
printList();
}
输出
如果我们编译并运行上面的程序,那么它将产生以下输出 -
Original List: [ (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) ] Deleted value:(6,56) Deleted value:(5,40) Deleted value:(4,1) Deleted value:(3,30) Deleted value:(2,20) Deleted value:(1,10) List after deleting all items: [ ] Restored List: [ (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) ] Element found: (4,1) List after deleting an item: [ (6,56) (5,40) (3,30) (2,20) (1,10) ] Element not found. List after sorting the data: [ (1,10) (2,20) (3,30) (5,40) (6,56) ] List after reversing the data: [ (6,56) (5,40) (3,30) (2,20) (1,10) ]