W tym poście chciałbym opisać sposób wykonania listy powiązanej (ang. Linked list) w C.
Linked list jest to liniowa struktura danych nieposiadająca zdeklarowanej długości. Opiszę przykładowe rozwiązanie jednokierunkowe, czyli każdy element będzie zawierał wskaźnik na następny element z listy.
Funkcje obsługujące będą wykonywać następujące operacje:
- Dodanie elementu do listy;
- Usunięcie elementu z listy;
- Usunięcie elementu o podanej wartości,
- Usunięcie elementu z podanej pozycji,
- Znalezienie elementu na liście,
- Sprawdzenie czy lista jest pusta,
- Obliczenie wielkości listy,
- Odwrócenie elementów lisy.
Struktura przechowująca dane wygląda następująco:
- struct LinkedListData_s {
- uint8_t data;
- struct LinkedListData_s* nextEl;
- };
W liście można umieszczać każdy rodzaj danych jaki jest potrzebny. Jedynym niezmiennym elementem jest wskaźnik na kolejny element w tablicy. Bez niego, lub gdy zostanie on przypadkowo usunięty, lista będzie bezużyteczna, ponieważ nie uda się odnaleźć kolejnej wartości.
Dodanie elementu na początek listy:
- void ll_insert_first_element(struct LinkedListData_s * headData, struct LinkedListData_s ** headPtr, uint8_t data) {
- struct LinkedListData_s *lldata = (struct LinkedListData_s*)malloc(sizeof(struct LinkedListData_s));
- lldata->data = data;
- lldata->nextEl = headData;
- *headPtr = lldata;
- }
Usunięcie elementu z początku listy:
- struct LinkedListData_s* ll_delete_first_element(struct LinkedListData_s *headPtr) {
- struct LinkedListData_s *tempPtr = headPtr;
- if(headPtr == NULL) { return NULL; }
- head = tempPtr->nextEl;
- return tempPtr;
- }
Usunięcie pierwszego elementu o podanej wartości:
- struct LinkedListData_s* ll_delete_by_value(struct LinkedListData_s *headPtr, uint8_t value) {
- struct LinkedListData_s* cur = headPtr;
- struct LinkedListData_s* prev = NULL;
- if(head == NULL) { return NULL; }
- while(cur->data != value) {
- if(cur->nextEl == NULL) { return NULL; }
- else {
- prev = cur;
- cur = cur->nextEl;
- }
- }
- if(cur == headPtr) { headPtr = headPtr->nextEl; }
- else { prev->nextEl = cur->nextEl; }
- return cur;
- }
Usunięcie elementu o podanej pozycji:
- struct LinkedListData_s* ll_delete_by_position(struct LinkedListData_s *headPtr, uint8_t position) {
- struct LinkedListData_s* cur = headPtr;
- struct LinkedListData_s* prev = NULL;
- uint16_t act_pos = 0;
- if(head == NULL) { return NULL; }
- while(act_pos != position) {
- act_pos++;
- if(cur->nextEl == NULL) { return NULL; }
- else {
- prev = cur;
- cur = cur->nextEl;
- }
- }
- if(cur == headPtr) { headPtr = headPtr->nextEl; }
- else { prev->nextEl = cur->nextEl; }
- return cur;
- }
Wyświetlenie wszystkich elementów zapisanych na liście:
- void ll_print_list(struct LinkedListData_s *headPtr) {
- struct LinkedListData_s *ptr = headPtr;
- while(ptr != NULL) {
- printf("((DEC) - %d; (HEX) - 0x%.2x\r\n", ptr->data, ptr->data);
- ptr = ptr->nextEl;
- }
- }
Wyszukanie elementu na liście:
- int32_t ll_search_value(struct LinkedListData_s *headPtr, uint8_t value) {
- struct LinkedListData_s *ptr = headPtr;
- uint16_t positionInList = 0;
- while(ptr != NULL) {
- if(ptr->data == value) {
- return positionInList;
- }
- positionInList++;
- ptr = ptr->nextEl;
- }
- return -1;
- }
Pobranie rozmiaru:
- uint16_t ll_get_list_size(struct LinkedListData_s *headPtr) {
- struct LinkedListData_s *ptr = headPtr;
- uint16_t list_len = 0;
- while(ptr != NULL) {
- list_len++;
- ptr = ptr->nextEl;
- }
- return list_len;
- }
Odwrócenie listy:
- void ll_reverse_data(struct LinkedListData_s** headPtr) {
- struct LinkedListData_s* current = *headPtr;
- struct LinkedListData_s* prev = NULL;
- struct LinkedListData_s* next = NULL;
- while (current != NULL) {
- next = current->nextEl;
- current->nextEl = prev;
- prev = current;
- current = next;
- }
- *headPtr = prev;
- }